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.
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.
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_PEERS fetches a missing field for all instances that came from
the same QuerySet.
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.
RAISE raises a FieldFetchBlocked
exception.
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.
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.
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 isempty lookup and
IsEmpty()
database function are now supported on SpatiaLite.
The new num_dimensions lookup and NumDimensions() database function
allow filtering geometries by the number of dimensions on PostGIS and
SpatiaLite.
django.contrib.messages¶…
django.contrib.postgres¶inspectdb now introspects
HStoreField when psycopg 3.2+ is
installed and django.contrib.postgres is in INSTALLED_APPS.
django.contrib.redirects¶…
django.contrib.sessions¶…
django.contrib.sitemaps¶…
django.contrib.sites¶…
django.contrib.staticfiles¶…
…
…
…
…
…
…
…
…
…
…
…
…
…
Management commands now set ArgumentParser's
suggest_on_error argument to True by default on Python 3.14, enabling
suggestions for mistyped subcommand names and argument choices.
…
QuerySet.in_bulk() now supports chaining after
QuerySet.values() and QuerySet.values_list().
The new JSONNull expression provides an explicit
way to represent the JSON scalar null. It can be used when saving a
top-level JSONField value, or querying for
top-level or nested JSON null values. See
Storing and querying for None for usage examples and some caveats.
DecimalField.max_digits
and DecimalField.decimal_places are no longer required to be
set on Oracle, PostgreSQL, and SQLite.
JSONField now supports
negative array indexing on Oracle
21c+.
…
…
…
…
…
…
…
…
…
…
…
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 for DurationField, 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_delete is 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 None in an
ArrayField with a
JSONField base field are now saved as SQL NULL
instead of the JSON null primitive. This matches the behavior of a
standalone JSONField when storing None values.
The check management command now supplies all databases if not
specified. Callers should be prepared for databases to be accessed.
Upstream support for PostgreSQL 14 ends in November 2026. Django 6.1 supports PostgreSQL 15 and higher.
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.
GenericForeignKey now uses a
separate descriptor class: the private GenericForeignKeyDescriptor.
The minimum supported version of SQLite is increased from 3.31.0 to 3.37.0.
Calling QuerySet.values_list() with flat=True and no field name
is deprecated. Pass an explicit field name, like
values_list("pk", flat=True).
The use of None to represent a top-level JSON scalar null when
querying JSONField is now deprecated in favor of
the new JSONNull expression. At the end
of the deprecation period, None values compile to SQL IS NULL when
used as the top-level value. Key and index lookups
are unaffected by this deprecation.
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 all parameter for the django.contrib.staticfiles.finders.find()
function is removed in favor of the find_all parameter.
Fallbacks to request.user and request.auser() when user is
None in django.contrib.auth.login() and
django.contrib.auth.alogin(), respectively, are removed.
The ordering keyword parameter of the PostgreSQL specific aggregation
functions django.contrib.postgres.aggregates.ArrayAgg,
django.contrib.postgres.aggregates.JSONBAgg, and
django.contrib.postgres.aggregates.StringAgg are removed in favor
of the order_by parameter.
Support for subclasses of RemoteUserMiddleware that override
process_request() without overriding aprocess_request() is
removed.
Nov 30, 2025