Django 5.2 release notes - UNDER DEVELOPMENT¶
Expected April 2025
Welcome to Django 5.2!
These release notes cover the new features, as well as some backwards incompatible changes you should be aware of when upgrading from Django 5.1 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 5.2 is designated as a long-term support release. It will receive security updates for at least three years after its release. Support for the previous LTS, Django 4.2, will end in April 2026.
Python compatibility¶
Django 5.2 supports Python 3.10, 3.11, 3.12, and 3.13. We highly recommend and only officially support the latest release of each series.
What’s new in Django 5.2¶
Composite Primary Keys¶
The new django.db.models.CompositePrimaryKey
allows tables to be
created with a primary key consisting of multiple fields.
To use a composite primary key, when creating a model set the pk
field to
be a CompositePrimaryKey
:
from django.db import models
class Release(models.Model):
pk = models.CompositePrimaryKey("version", "name")
version = models.IntegerField()
name = models.CharField(max_length=20)
See Composite primary keys for more details.
Minor features¶
django.contrib.admin
¶
The
admin/base.html
template now has a new block extrabody for adding custom code before the closing</body>
tag.
django.contrib.admindocs
¶
Links to components in docstrings now supports custom link text, using the format
:role:`link text <link>`
. See documentation helpers for more details.The model pages are now restricted to users with the corresponding view or change permissions.
django.contrib.auth
¶
The default iteration count for the PBKDF2 password hasher is increased from 870,000 to 1,000,000.
The following new asynchronous methods are now provided, using an
a
prefix:Auth backends can now provide async implementations which are used when calling async auth functions (e.g.
aauthenticate()
) to reduce context-switching which improves performance. See adding an async interface for more details.The password validator classes now have a new method
get_error_message()
, which can be overridden in subclasses to customize the error messages.
django.contrib.contenttypes
¶
…
django.contrib.gis
¶
GDAL now supports curved geometries
CurvePolygon
,CompoundCurve
,CircularString
,MultiSurface
, andMultiCurve
via the newOGRGeometry.has_curve
property, and theOGRGeometry.get_linear_geometry()
andOGRGeometry.get_curve_geometry()
methods.coveredby
andisvalid
lookups,Collect
aggregation, andGeoHash
andIsValid
database functions are now supported on MariaDB 11.7+.
django.contrib.messages
¶
…
django.contrib.postgres
¶
…
django.contrib.redirects
¶
…
django.contrib.sessions
¶
…
django.contrib.sitemaps
¶
…
django.contrib.sites
¶
…
django.contrib.staticfiles
¶
…
Asynchronous views¶
…
Cache¶
…
CSRF¶
…
Database backends¶
MySQL connections now default to using the
utf8mb4
character set, instead ofutf8
, which is an alias for the deprecated character setutf8mb3
.
Decorators¶
method_decorator()
now supports wrapping asynchronous view methods.
Email¶
Tuple items of
EmailMessage.attachments
andEmailMultiAlternatives.attachments
are now named tuples, as opposed to regular tuples.EmailMultiAlternatives.alternatives
is now a list of named tuples, as opposed to regular tuples.The new
body_contains()
method returns a boolean indicating whether a provided text is contained in the emailbody
and in all attached MIME typetext/*
alternatives.
Error Reporting¶
The attribute
SafeExceptionReporterFilter.hidden_settings
now treats values as sensitive if their name includesAUTH
.
File Storage¶
…
File Uploads¶
…
Forms¶
The new
ColorInput
form widget is for entering a color inrrggbb
hexadecimal format and renders as<input type="color" ...>
. Some browsers support a visual color picker interface for this input type.The new
SearchInput
form widget is for entering search queries and renders as<input type="search" ...>
.The new
TelInput
form widget is for entering telephone numbers and renders as<input type="tel" ...>
.The new
field_id
argument forErrorList
allows an HTMLid
attribute to be added in the error template. SeeErrorList.field_id
for details.
Generic Views¶
…
Internationalization¶
…
Logging¶
…
Management Commands¶
A new warning is displayed when running
runserver
, indicating that it is unsuitable for production. This warning can be suppressed by setting theHIDE_PRODUCTION_WARNING
environment variable to"true"
.The
makemigrations
andmigrate
commands have a newCommand.autodetector
attribute for subclasses to override in order to use a custom autodetector class.
Migrations¶
The new operation
AlterConstraint
is a no-op operation that alters constraints without dropping and recreating constraints in the database.
Models¶
The
SELECT
clause generated when usingQuerySet.values()
andQuerySet.values_list()
now matches the specified order of the referenced expressions. Previously, the order was based of a set of counterintuitive rules which made query combination through methods such asQuerySet.union()
unpredictable.Added support for validation of model constraints which use a
GeneratedField
.The new
Expression.set_returning
attribute specifies that the expression contains a set-returning function, enforcing subquery evaluation. This is necessary for many Postgres set-returning functions.CharField.max_length
is no longer required to be set on SQLite, which supports unlimitedVARCHAR
columns.QuerySet.explain()
now supports thememory
andserialize
options on PostgreSQL 17+.
Requests and Responses¶
The new
HttpResponse.text
property provides the string representation ofHttpResponse.content
.The new
HttpRequest.get_preferred_type()
method can be used to query the preferred media type the client accepts.The new
preserve_request
argument forHttpResponseRedirect
andHttpResponsePermanentRedirect
determines whether the HTTP status codes 302/307 or 301/308 are used, respectively.The new
preserve_request
argument forredirect()
allows to instruct the user agent to reuse the HTTP method and body during redirection using specific status codes.
Security¶
…
Serialization¶
Each serialization format now defines a
Deserializer
class, rather than a function, to improve extensibility when defining a custom serialization format.
Signals¶
…
Templates¶
The new
simple_block_tag()
decorator enables the creation of simple block tags, which can accept and use a section of the template.
Tests¶
Stack frames from Django’s custom assertions are now hidden. This makes test failures easier to read and enables
test --pdb
to directly enter into the failing test method.Data loaded from
fixtures
and from migrations enabled with serialized_rollback=True are now available duringTransactionTestCase.setUpClass()
.
URLs¶
…
Utilities¶
SafeString
now returnsNotImplemented
in__add__
for non-string right-hand side values. This aligns with thestr
addition behavior and allows__radd__
to be used if available.format_html_join()
now supports taking an iterable of mappings, passing their contents as keyword arguments toformat_html()
.
Validators¶
…
Backwards incompatible changes in 5.2¶
Database backend API¶
This section describes changes that may be needed in third-party database backends.
The new
Model._is_pk_set()
method allows checking if a Model instance’s primary key is defined.BaseDatabaseOperations.adapt_decimalfield_value()
is now a no-op, simply returning the given value.
django.contrib.gis
¶
Support for PostGIS 3.0 is removed.
Support for GDAL 3.0 is removed.
Dropped support for PostgreSQL 13¶
Upstream support for PostgreSQL 13 ends in November 2025. Django 5.2 supports PostgreSQL 14 and higher.
Changed MySQL connection character set default¶
MySQL connections now default to using the utf8mb4
character set, instead
of utf8
, which is an alias for the deprecated character set utf8mb3
.
utf8mb3
can be specified in the OPTIONS
part of the DATABASES
setting, if needed for legacy databases.
Miscellaneous¶
Adding
EmailMultiAlternatives.alternatives
is now only supported via theattach_alternative()
method.The minimum supported version of
gettext
is increased from 0.15 to 0.19.HttpRequest.accepted_types
is now sorted by the client’s preference, based on the request’sAccept
header.The attributes
UniqueConstraint.violation_error_code
andUniqueConstraint.violation_error_message
are now always used when provided. Previously, they were ignored ifUniqueConstraint.fields
was set without aUniqueConstraint.condition
.The
debug()
context processor is no longer included in the default project template.The following methods now have
alters_data=True
set to prevent side effects when rendering a template context:
Features deprecated in 5.2¶
Miscellaneous¶
The
all
argument for thedjango.contrib.staticfiles.finders.find()
function is deprecated in favor of thefind_all
argument.The fallback to
request.user
whenuser
isNone
indjango.contrib.auth.login()
anddjango.contrib.auth.alogin()
will be removed.