$ cat django/month/2026-09-01.log
the month in review · September 2026
Django drops PostgreSQL 15 and PostGIS 3.2
By RepoJournal · composed from the cited sources · human-reviewed weekly · methodology
September also brought the 6.1.2/6.0.9/5.2.18 release dates, a batch of ORM regression fixes, and ASGI middleware context switching cut.
Fixed #37263 -- Fixed changelist __exact search crashes and over-matching. django/django
Search terms for non-text __exact entries in search_fields were validated with the model field's formfield().to_python(), which let invalid terms through for fields with choices and set a changelist search up to crash or over-match. If your admin search_fields include choice-backed fields, this is the fix.
Fixed #37300 -- Fixed database routing for custom forward prefetch querysets. django/django
Custom querysets passed to forward ForeignKey and reverse OneToOneField prefetches lost the parent instance database routing hint in 6.1 and could hit the wrong database. The fix restores the hint. If you use multiple databases with custom prefetch querysets, check your 6.1 upgrade against this.
Fixed #37309 -- Used _is_pk_set() in Model.__eq__ and the XML serializer. django/django
Model.__eq__ and the XML serializer decided whether an instance was unsaved with pk is None, which is wrong for composite primary keys (pk is a tuple like (None, None)) and for db_default PKs, where DatabaseDefault is not None. Distinct unsaved instances compared equal, and XML dumps emitted a dummy pk attribute; both now use _is_pk_set().
Fixed #37222 -- Fixed QuerySet.distinct() crash on duplicated selections. django/django
A regression from 65ad4ade caused a crash when two lookup paths resolved to the same column and ordering referred to each selection by its own position. QuerySet.distinct() on duplicated selections was broken on PostgreSQL, which binds a DISTINCT ON clause to those positions.
Improve search performance django/djangoproject.com
Searches returning around 200 results, such as "Model", were traced to headline annotations being computed on every row before the limit was applied. Moving the annotation after the paginator derives offset and limit took the query from 850ms to 250ms.
Fixed #37312, Refs #36605 -- Fixed annotation preservation and key selection in in_bulk(). django/django
QuerySet.in_bulk() rebuilt values() and values_list() projections from query.values_select, dropping annotations and mis-selecting keys. If you call in_bulk() on an annotated queryset, the annotations now survive.
Fixed #37237 -- Improved RelatedIn lookup preparation performance. django/django
The RelatedIn lookup preparation path got a performance improvement, with the implementation idea credited to Simon Charette. It cuts the per-query overhead of related-field __in lookups.
Fixed #37311 -- Prevented consumption of rhs iterators in annotation lookups. django/django
In and range lookups against an annotation on the left-hand side consumed iterator right-hand sides while preparing the query. The iterator is now materialized once before its values are checked for expressions, so a generator passed to __in survives the lookup.
$ ls django/month/ # the briefings behind this review
Keep up with Django in about 3 minutes: what actually shipped — the commits, pull requests, releases, and security advisories that matter.
fair warning: these emails are deeply technical. diffs, version numbers, CVEs, benchmark deltas. if that's not your idea of a good read, this isn't your newsletter.
Folds into your digest — weekly by default, monthly if you prefer. Unsubscribe in one click.