Django 6.1 release notes - UNDER DEVELOPMENT¶
Expected August 2026
Welcome to Django 6.1!
These release notes cover the new features, as well as some backwards incompatible changes you’ll want to be aware of when upgrading from Django 6.0 or earlier. We’ve begun the deprecation process for some features.
See the How to upgrade Django to a newer version guide if you’re updating an existing project.
Python compatibility¶
Django 6.1 supports Python 3.12, 3.13, and 3.14. We highly recommend, and only officially support, the latest release of each series.
What’s new in Django 6.1¶
Model field fetch modes¶
The on-demand fetching behavior of model fields is now configurable with fetch modes. These modes allow you to control how Django fetches data from the database when an unfetched field is accessed.
Django provides three fetch modes:
FETCH_ONE, the default, fetches the missing field for the current instance only. This mode represents Django’s existing behavior.FETCH_PEERSfetches a missing field for all instances that came from the sameQuerySet.This mode works like an on-demand
prefetch_related(). It can reduce most cases of the “N+1 queries problem” to two queries without any work to maintain a list of fields to prefetch.RAISEraises aFieldFetchBlockedexception.This mode can prevent unintentional queries in performance-critical sections of code.
Use the new method QuerySet.fetch_mode() to set the fetch mode for model
instances fetched by the QuerySet:
from django.db import models
books = Book.objects.fetch_mode(models.FETCH_PEERS)
for book in books:
print(book.author.name)
Despite the loop accessing the author foreign key on each instance, the
FETCH_PEERS fetch mode will make the above example perform only two
queries:
Fetch all books.
Fetch associated authors.
See fetch modes for more details.
Database-level delete options for ForeignKey.on_delete¶
ForeignKey.on_delete now supports database-level delete options:
These options handle deletion logic entirely within the database, using the SQL
ON DELETE clause. They are thus more efficient than the existing
Python-level options, as Django does not need to load objects before deleting
them. As a consequence, the DB_CASCADE option does
not trigger the pre_delete or post_delete signals.
Minor features¶
django.contrib.admin¶
The admin site login view now redirects authenticated users to the next URL, if available, instead of always redirecting to the admin index page.
django.contrib.admindocs¶
…
django.contrib.auth¶
The default iteration count for the PBKDF2 password hasher is increased from 1,200,000 to 1,500,000.
django.contrib.contenttypes¶
…
django.contrib.gis¶
The
isemptylookup andIsEmpty()database function are now supported on SpatiaLite.The new
num_dimensionslookup andNumDimensions()database function allow filtering geometries by the number of dimensions on PostGIS and SpatiaLite.
django.contrib.messages¶
…
django.contrib.postgres¶
inspectdbnow introspectsHStoreFieldwhenpsycopg3.2+ is installed anddjango.contrib.postgresis inINSTALLED_APPS.
django.contrib.redirects¶
…
django.contrib.sessions¶
…
django.contrib.sitemaps¶
…
django.contrib.sites¶
…
django.contrib.staticfiles¶
…
Asynchronous views¶
…
Cache¶
…
CSP¶
…
CSRF¶
…
Decorators¶
…
Email¶
…
Error Reporting¶
…
File Storage¶
…
File Uploads¶
…
Forms¶
…
Generic Views¶
…
Internationalization¶
…
Logging¶
…
Management Commands¶
Management commands now set
ArgumentParser'ssuggest_on_errorargument toTrueby default on Python 3.14, enabling suggestions for mistyped subcommand names and argument choices.
Migrations¶
…
Models¶
QuerySet.in_bulk()now supports chaining afterQuerySet.values()andQuerySet.values_list().The new
JSONNullexpression provides an explicit way to represent the JSON scalarnull. It can be used when saving a top-levelJSONFieldvalue, or querying for top-level or nested JSONnullvalues. See Storing and querying for None for usage examples and some caveats.DecimalField.max_digitsandDecimalField.decimal_placesare no longer required to be set on Oracle, PostgreSQL, and SQLite.JSONFieldnow supports negative array indexing on Oracle 21c+.GeneratedFieldnow supports stored columns (db_persistset toTrue) on Oracle 23ai/26ai (23.7+).
Pagination¶
…
Requests and Responses¶
…
Security¶
…
Serialization¶
Subclasses of models defining the
natural_key()method can now opt out of natural key serialization by overriding the method to return an empty tuple:(). This ensures primary keys are serialized when usingdumpdata --natural-primary.
Signals¶
…
Tasks¶
…
Templates¶
…
Tests¶
…
URLs¶
…
Utilities¶
…
Validators¶
…
Backwards incompatible changes in 6.1¶
Database backend API¶
This section describes changes that may be needed in third-party database backends.
The
DatabaseOperations.adapt_durationfield_value()hook is added. If the database has native support forDurationField, override this method to simply return the value.The
DatabaseIntrospection.get_relations()should now return a dictionary with 3-tuples containing (field_name_other_table,other_table,db_on_delete) as values.db_on_deleteis one of the database-level delete options e.g.DB_CASCADE.
django.contrib.gis¶
Support for PostGIS 3.1 is removed.
Support for GEOS 3.8 is removed.
Support for GDAL 3.1 and 3.2 is removed.
django.contrib.postgres¶
Top-level elements set to
Nonein anArrayFieldwith aJSONFieldbase field are now saved as SQLNULLinstead of the JSONnullprimitive. This matches the behavior of a standaloneJSONFieldwhen storingNonevalues.
System checks¶
The
checkmanagement command now supplies alldatabasesif not specified. Callers should be prepared for databases to be accessed.
Dropped support for PostgreSQL 14¶
Upstream support for PostgreSQL 14 ends in November 2026. Django 6.1 supports PostgreSQL 15 and higher.
Dropped support for MySQL < 8.4¶
Upstream support for MySQL 8.0 ends in April 2026, and MySQL 8.1-8.3 are short-term innovation releases. Django 6.1 supports MySQL 8.4 and higher.
Miscellaneous¶
GenericForeignKeynow uses a separate descriptor class: the privateGenericForeignKeyDescriptor.The minimum supported version of SQLite is increased from 3.31.0 to 3.37.0.
Features deprecated in 6.1¶
Miscellaneous¶
Calling
QuerySet.values_list()withflat=Trueand no field name is deprecated. Pass an explicit field name, likevalues_list("pk", flat=True).The use of
Noneto represent a top-level JSON scalarnullwhen queryingJSONFieldis now deprecated in favor of the newJSONNullexpression. At the end of the deprecation period,Nonevalues compile to SQLIS NULLwhen used as the top-level value.Key and index lookupsare unaffected by this deprecation.
Features removed in 6.1¶
These features have reached the end of their deprecation cycle and are removed in Django 6.1.
See Features deprecated in 5.2 for details on these changes, including how to remove usage of these features.
The
allparameter for thedjango.contrib.staticfiles.finders.find()function is removed in favor of thefind_allparameter.Fallbacks to
request.userandrequest.auser()whenuserisNoneindjango.contrib.auth.login()anddjango.contrib.auth.alogin(), respectively, are removed.The
orderingkeyword parameter of the PostgreSQL specific aggregation functionsdjango.contrib.postgres.aggregates.ArrayAgg,django.contrib.postgres.aggregates.JSONBAgg, anddjango.contrib.postgres.aggregates.StringAggare removed in favor of theorder_byparameter.Support for subclasses of
RemoteUserMiddlewarethat overrideprocess_request()without overridingaprocess_request()is removed.