skip to navigation
skip to content

Planet Python

Last update: April 17, 2026 04:44 PM UTC

April 17, 2026


Mike Driscoll

Textual – An Intro to DOM Queries (Part I)

In this article, you will learn how to query the DOM in Textual. You will discover that the DOM keeps track of all the widgets in your application. By running queries against the DOM, you can find widgets quickly and update them, too. You will be learning the following topics related to the DOM: The […]

The post Textual – An Intro to DOM Queries (Part I) appeared first on Mouse Vs Python.

April 17, 2026 12:57 PM UTC


Real Python

The Real Python Podcast – Episode #291: Reassessing the LLM Landscape & Summoning Ghosts

What are the current techniques being employed to improve the performance of LLM-based systems? How is the industry shifting from post-training towards context engineering and multi-agent orchestration? This week on the show, Jodie Burchell, data scientist and Python Advocacy Team Lead at JetBrains, returns to discuss the current AI coding landscape.

April 17, 2026 12:00 PM UTC

Quiz: Working With Python Virtual Environments

Test your knowledge of Python virtual environments, from creating and activating them to installing packages with pip.

April 17, 2026 12:00 PM UTC

April 16, 2026


Talk Python to Me

#545: OWASP Top 10 (2025 List) for Python Devs

The OWASP Top 10 just got a fresh update, and there are some big changes: supply chain attacks, exceptional condition handling, and more. Tanya Janca is back on Talk Python to walk us through every single one of them. And we're not just talking theory, we're going to turn Claude Code loose on a real open source project and see what it finds. Let's do it.

April 16, 2026 08:24 PM UTC


Django Weblog

New Technical Governance - request for community feedback

Hello Django community,

The Steering Council is excited to share our proposed new technical governance and ask for your feedback. Last year we suspended the formal voting process of the Steering Council. The updates we’re proposing would bring how we’ve been operating into alignment with the written governance.

From the motivation section:

This is a revisitation of Django's technical governance in which a simplification and reduction was made to make it more approachable to more people. The goals of these changes are the following:

  • Make it easier to enact our governance.
  • Make it easier for others to understand our governance.
  • Make the governance more flexible, allowing more action with less procedure.

You can read DEP 0019 here.

Adoption plan

The goal is to have this governance accepted and in place by 2026-07-01. Our timeline is as follows, but may change depending on feedback.

What we need from you

We would like to know if we are achieving our goals with this document. For example, do you feel that this makes our governance easier to understand, do you feel like you have a better understanding of who is eligible to run for the Steering Council, is it clear how Django operates from a process perspective?

Beyond that, if you have other feedback around the changes, please share it. This has gone through a high degree of review from the Steering Council and Board over the past 5 months, but that doesn’t mean there aren't areas where it can be improved.

Anyone can participate in this process on the Forum thread here.

April 16, 2026 07:59 PM UTC

PyCharm & Django annual fundraiser

For another year, we are thrilled to partner with our friends at JetBrains on the annual "Buy PyCharm, Support Django" campaign. This is the first of two fundraisers we're running with JetBrains this year, and it's one of the most impactful ways the community can support the Django Software Foundation.

"JetBrains is a cornerstone in the Django community, consistently helping us understand our evolving landscape. Their annual survey provides invaluable insights into the community's needs, trends, and tools, ensuring we stay on the pulse of what matters most."

Jeff Triplett, President, Django Software Foundation

Your support of this campaign helps fund key initiatives such as:

How the campaign works

From today to May 1, when you purchase PyCharm at a 30% discount through our special campaign link, JetBrains will donate an equal amount to the Django Software Foundation. You get a professional IDE that's trusted by Django developers worldwide, and the DSF receives a matched contribution.

Get 30% off PyCharm, Support Django

Thank you, JetBrains

Beyond this campaign, JetBrains contributes to the Django ecosystem in ways that are easy to overlook but hard to overstate. Their Django Developers Survey, State of Django report, and broader Python Developers Survey give the entire community a clearer picture of where Django and Python are heading each year.

"JetBrains is one of our most generous fundraising partners year after year, helping us sustain and grow the Django ecosystem. We deeply appreciate their commitment, leadership, and collaboration."

Thank you to JetBrains for another year of partnership, and thank you to everyone who participates in this campaign. Together, we can ensure the continued success and growth of the framework we all rely on.

Other ways to donate

If you would like to donate in another way, especially if you are already a PyCharm customer, here are other ways to donate to the DSF:

April 16, 2026 05:45 PM UTC


Python Software Foundation

Announcing Python Software Foundation Fellow Members for Q4 2025! 🎉

April 16, 2026 02:45 PM UTC


Real Python

Quiz: Welcome to Real Python!

Get a tour of Real Python, find resources for your skill level, and learn how to use the community to study effectively.

April 16, 2026 12:00 PM UTC

Learning Path: Python Game Development

Build Python games from command-line projects to 2D graphical games with turtle, Tkinter, Pygame, and Arcade.

April 16, 2026 12:00 PM UTC


death and gravity

Learn Python object-oriented programming with Raymond Hettinger

Even if you haven't heard of Raymond Hettinger, you've definitely used his work, bangers such as sorted(), collections, and many others. His talks had a huge impact on my development as a software engineer, are some of the best I've heard, and are the reason *you should not be afraid of inheritance* anymore.

April 16, 2026 09:00 AM UTC


Bruno Ponne / Coding The Past

Exploring the MET API with Python - Francisco Goya's Artworks

The act of painting is about one heart telling another heart where he found salvation.

— Francisco Goya


Francisco Goya is one of my favorite artists. His work has a beautiful darkness that tells a lot about his experience in his time. In this post, we’ll dive into his world using the Metropolitan Museum of Art (MET) application programming interface (API), which gives developers access to data on hundreds of thousands of artworks.


You will learn how to interact with the MET API using Python. We will journey through the process of making HTTP requests, parsing the returned JSON data into a structured pandas DataFrame, and exploring the collection to extract meaningful insights about Goya’s work.


1. Requesting data from the API


We begin by importing the requests library, which allows us to send HTTP requests to the MET REST API in Python. We’ll query the search endpoint to find Goya’s paintings. In API terms, an endpoint is a specific URL used to access a particular resource.


The MET API has four endpoints starting with “https://collectionapi.metmuseum.org/”:


You can find more details about each endpoint and its functionality in the official MET API documentation.

tips_and_updates  
A REST (Representational State Transfer) API is a set of rules used to communicate between your computer and the MET server using HTTP methods and endpoints. Note that many APIs require authentication; however, the MET API is public and does not require an API key.


content_copy Copy

import requests
import pandas as pd

search_query = "https://collectionapi.metmuseum.org/public/collection/v1/search?hasImages=true&q=Francisco Goya"

response = requests.get(search_query)
search_data = response.json()

print(f"Found {search_data['total']} artworks for Francisco Goya.")


API endpoints can be followed by query parameters that refine our search. In the example above, hasImages=true filters for objects with images, and q specifies our search term—in this case, the artist’s name.


The requests library contains a method called get(), which we use to send our request to the API, passing our endpoint saved in the string search_query.


The resulting response object can then be parsed into a JSON structure using the .json() method.


2. Converting JSON to a list of painting ids


While JSON is the standard for data exchange, working with raw JSON can be cumbersome for direct data analysis. In Python, you can think of JSON as a dictionary of keys and values. These values can themselves be other dictionaries, lists, numbers, strings, or booleans. By printing the search_data object, we can see that it’s a dictionary containing two main keys:


To retrieve the list of IDs associated with the key “objectIDs” we use the standard dictionary notation search_data["objectIDs"] and save it to the variable goya_ids.


content_copy Copy

print(search_data)
goya_ids = search_data["objectIDs"]


3. Getting the details of each of Goya’s works


To retrieve details for each artwork — such as its title, date, and thematic tags — we need to iterate through the list of IDs and send a request to the /objects/{objectID} endpoint for each item. We implement this using a for loop that repeats the request for each artwork.


(Note: Depending on the number of results, fetching these details can take a few minutes. We use time.sleep(1) to respect the API’s rate limits and avoid being blocked.)


content_copy Copy

import time

all_objects_data = []


for object_id in goya_ids:
    try:
        obj_response = requests.get(f"https://collectionapi.metmuseum.org/public/collection/v1/objects/{object_id}")
        obj_response.raise_for_status() 
        all_objects_data.append(obj_response.json())
    except requests.exceptions.RequestException as e:
        print(f"Error for object ID {object_id}: {e}")
    
    time.sleep(1) # Respect the API, one request per second to be safe

# Convert the gathered data to a DataFrame
goya_df = pd.json_normalize(all_objects_data)

# Filter only Goya works
goya_df = goya_df[goya_df['artistDisplayName'].str.contains('Goya', na=False)]


We use a try-except block to ensure the loop continues even if a specific object ID fails to load. We also log any errors to help with debugging.


Finally, we convert the collected data into a Pandas DataFrame using pd.json_normalize. Since a broad search might return works about Goya or mentioning him in metadata, we filter the DataFrame to ensure the artistDisplayName actually contains “Goya.”


The resulting DataFrame contains intriguing data about each of his works, including name, year when the painting or drawing was started and finished, descriptive tags and dimensions, among other information. Feel free to explore it. We will continue working with the descriptive tags in the next steps.


4. Flattening nested JSON data


For keys whose values are lists or other dictionaries, the resulting columns will contain those respective objects. This happens, for example, with the tags column. When you have nested elements like this, you can “flatten” them into a tabular format.


JSON structure

JSON data structure


Flattening an element changes the granularity of the data. Whereas before each row represented a single artwork, in the flattened table each row represents an individual tag belonging to one artwork.


To flatten these nested tags, we can use json_normalize by specifying the element to unnest in the record_path. We also include the objectID in the meta parameter so we don’t lose the relationship between a tag and its original artwork. Later on, we can join this tags table back to our main DataFrame if we want.


content_copy Copy

tags_df = pd.json_normalize(
    all_objects_data,
    record_path='tags',
    meta=['objectID']
)


5. Visualizing the most frequent themes


The MET API provides a tags field containing descriptive terms associated with each artwork. To understand the prevailing themes in Goya’s works — famous for documenting the social upheaval and dark realities of his era — we can extract these terms and calculate their frequency.


Once we isolate the individual tags into a new column, we can use matplotlib to create a horizontal bar plot of the top 10 terms and check if indeed his artwork contained themes related to death and misery.


content_copy Copy

import matplotlib.pyplot as plt

# Calculate the frequency of each term for the filtered Goya artworks
# We filter tags_df to only include IDs present in our filtered goya_df
term_frequency = tags_df[tags_df['objectID'].isin(goya_df['objectID'])]['term'].value_counts().reset_index()
term_frequency.columns = ['term', 'count']

# Select the top N terms for better readability if there are many unique terms
# For this example, let's take the top 10 terms
top_terms = term_frequency.head(10).sort_values(by='count', ascending=True)

plt.figure(figsize=(12, 8))
plt.barh(top_terms['term'], top_terms['count'], color='#FF6885')

plt.title('Top 10 Most Frequent Terms in Goya Dataset', fontsize=20)
plt.xlabel('Frequency', fontsize=16)
plt.ylabel('Term', fontsize=16)
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
plt.tight_layout()
plt.show()


Top 10 Most Frequent Terms in Goya Dataset

Top 10 Most Frequent Terms chart


The resulting visualization provides a fascinating window into Goya’s thematic world. Beyond common subjects like “Men,” “Women,” and “Portraits,” we see a strong representation of “Bulls” (reflecting his famous Tauromaquia series) and “Self-portraits.”


Most strikingly, terms like “Death” and “Suffering” appear prominently in the top 10. This data-driven insight confirms Goya’s historical reputation as an artist who didn’t shy away from the darker aspects of the human experience. By quantifying these themes through the MET API, we move from subjective observation to empirical evidence of his artistic focus.


The sleep of reason produces monsters

Plate 43 from "Los Caprichos": The sleep of reason produces monsters (El sueño de la razon produce monstruos)


You could also use the main dataset we created to collect a series of images of Goya works. I am thinking of using AI to help me download all images of Goya in the public domain and try to build a model to describe or classify them in Python. Feel free to use the data and let me know about your analysis. Leave your comments or any questions below and happy coding!


Conclusions




April 16, 2026 12:00 AM UTC

April 15, 2026


Django Weblog

Django Has Adopted Contributor Covenant 3

We’re excited to announce that Django has officially adopted Contributor Covenant 3 as our new Code of Conduct! This milestone represents the completion of a careful, community-driven process that began earlier this year.

What We’ve Accomplished

Back in February, we announced our plan to adopt Contributor Covenant 3 through a transparent, multi-step process. Today, we’re proud to share that we’ve completed all three steps:

Step 1 (Completed February 2026): Established a community-driven process for proposing and reviewing changes to our Code of Conduct.

Step 2 (Completed March 2026): Updated our Enforcement Manual, Reporting Guidelines, and FAQs to align with Contributor Covenant 3 and incorporate lessons learned from our working group’s experience.

Step 3 (Completed April 2026): Adopted the Contributor Covenant 3 with Django-specific enhancements.

Why Contributor Covenant 3?

Contributor Covenant 3 represents a significant evolution in community standards, incorporating years of experience from communities around the world. The new version:

By adopting this widely-used standard, Django joins a global community of projects committed to fostering welcoming, inclusive spaces for everyone.

What’s New in Django’s Code of Conduct

While we’ve adopted Contributor Covenant 3 as our foundation, we’ve also made Django-specific enhancements:

You can view the complete changelog of changes at our Code of Conduct repository.

Community-Driven Process

This adoption represents months of collaborative work. The Code of Conduct Working Group reviewed community feedback, consulted with the DSF Board, and incorporated insights from our enforcement experience. Each step was completed through pull requests that were open for community review and discussion.

We’re grateful to everyone who participated in this process—whether by opening issues, commenting on pull requests, joining forum discussions, or simply taking the time to review and understand the changes.

Where to Find Everything

All of our Code of Conduct documentation is available on both djangoproject.com and our GitHub repository:

How You Can Continue to Help

The Code of Conduct is a living document that will continue to evolve with our community’s needs:

Thank You

Creating a truly welcoming and inclusive community is ongoing work that requires participation from all of us. Thank you for being part of Django’s community and for your commitment to making it a safe, respectful space where everyone can contribute and thrive.

If you have questions about the new Code of Conduct or our processes, please don’t hesitate to reach out to the Code of Conduct Working Group at conduct@djangoproject.com.


Posted by Dan Ryan on behalf of the Django Code of Conduct Working Group

April 15, 2026 08:49 PM UTC


Real Python

Variables in Python: Usage and Best Practices

Explore Python variables from creation to best practices, covering naming conventions, dynamic typing, variable scope, and type hints with examples.

April 15, 2026 02:00 PM UTC


PyCon

Introducing the 7 Companies on Startup Row at PyCon US 2026

April 15, 2026 01:03 PM UTC


Real Python

Quiz: Design and Guidance: Object-Oriented Programming in Python

Test your understanding of the SOLID design principles for writing cleaner, more maintainable object-oriented Python code.

April 15, 2026 12:00 PM UTC

April 14, 2026


PyCoder’s Weekly

Issue #730: Typing Django, Dictionaries, pandas vs Polars, and More (April 14, 2026)

April 14, 2026 07:30 PM UTC


Real Python

Vector Databases and Embeddings With ChromaDB

Learn how to use ChromaDB, an open-source vector database, to store embeddings and give context to large language models in Python.

April 14, 2026 02:00 PM UTC

Quiz: Explore Your Dataset With pandas

Test your pandas fundamentals: core structures, indexing, filtering, grouping, dtypes, and combining DataFrames.

April 14, 2026 12:00 PM UTC

Quiz: Altair: Declarative Charts With Python

Test your knowledge of Altair, the declarative data visualization library for Python that turns DataFrames into interactive charts.

April 14, 2026 12:00 PM UTC

Quiz: Vector Databases and Embeddings With ChromaDB

Test your knowledge of vector databases and ChromaDB, from cosine similarity and embeddings to querying collections and RAG.

April 14, 2026 12:00 PM UTC


Python Software Foundation

PyCon US 2026: Why we're asking you to think about your hotel reservation

April 14, 2026 10:13 AM UTC


Seth Michael Larson

Add Animal Crossing events to your digital calendar

April 14, 2026 12:00 AM UTC

April 13, 2026


Python Software Foundation

Reflecting on Five Years as the PSF’s First CPython Developer in Residence

April 13, 2026 02:01 PM UTC


Real Python

How to Add Features to a Python Project With Codex CLI

Learn how to use Codex CLI to add features to Python projects via the terminal. Master AI-powered coding without needing a browser or IDE plugins.

April 13, 2026 02:00 PM UTC


PyCon

How to Build Your PyCon US 2026 Schedule

April 13, 2026 12:21 PM UTC