{"title":"Django 5.1 release notes","version":"dev","locale":"en","docname":"releases/5.1","url":"/en/dev/releases/5.1/","canonical":"https://djangodocs.dev/en/dev/releases/5.1/","summary":"Welcome to Django 5.1! These release notes cover the new features, as well as some backwards incompatible changes you should be aware of when upgrading from…","html":"<h1>Django 5.1 release notes<a class=\"heading-anchor\" href=\"#django-5-1-release-notes\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p><em>August 7, 2024</em></p>\n<p>Welcome to Django 5.1!</p>\n<p>These release notes cover the <a class=\"reference internal\" href=\"#whats-new-5-1\"><span class=\"std std-ref\">new features</span></a>, as well as\nsome <a class=\"reference internal\" href=\"#backwards-incompatible-5-1\"><span class=\"std std-ref\">backwards incompatible changes</span></a> you\nshould be aware of when upgrading from Django 5.0 or earlier. We’ve\n<a class=\"reference internal\" href=\"#deprecated-features-5-1\"><span class=\"std std-ref\">begun the deprecation process for some features</span></a>.</p>\n<p>See the <a class=\"reference internal\" href=\"/en/dev/howto/upgrade-version/\"><span class=\"doc\">How to upgrade Django to a newer version</span></a> guide if you’re updating an existing\nproject.</p>\n<section id=\"python-compatibility\">\n<h2>Python compatibility<a class=\"heading-anchor\" href=\"#python-compatibility\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django 5.1 supports Python 3.10, 3.11, 3.12, and 3.13 (as of 5.1.3). We\n<strong>highly recommend</strong> and only officially support the latest release of each\nseries.</p>\n</section>\n<section id=\"what-s-new-in-django-5-1\">\n<span id=\"whats-new-5-1\"></span><h2>What’s new in Django 5.1<a class=\"heading-anchor\" href=\"#what-s-new-in-django-5-1\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"querystring-template-tag\">\n<h3><code class=\"docutils literal notranslate\">{% querystring %}</code> template tag<a class=\"heading-anchor\" href=\"#querystring-template-tag\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django 5.1 introduces the <a class=\"reference internal\" href=\"/en/dev/ref/templates/builtins/#std-templatetag-querystring\"><code class=\"xref std std-ttag docutils literal notranslate\">{% querystring %}</code></a> template\ntag, simplifying the modification of query parameters in URLs, making it easier\nto generate links that maintain existing query parameters while adding or\nchanging specific ones.</p>\n<p>For instance, navigating pagination and query strings in templates can be\ncumbersome. Consider this template fragment that dynamically generates a URL\nfor navigating to the next page within a paginated view:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"c\">{# Linebreaks added for readability, this should be one, long line. #}</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;?</span><span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">key</span><span class=\"o\">,</span> <span class=\"nv\">values</span> <span class=\"k\">in</span> <span class=\"nv\">request.GET.iterlists</span> <span class=\"cp\">%}</span>\n<span class=\"s\">  </span><span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">key</span> <span class=\"o\">!=</span> <span class=\"s2\">&quot;page&quot;</span> <span class=\"cp\">%}</span>\n<span class=\"s\">    </span><span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">value</span> <span class=\"k\">in</span> <span class=\"nv\">values</span> <span class=\"cp\">%}</span>\n<span class=\"s\">      </span><span class=\"cp\">{{</span> <span class=\"nv\">key</span> <span class=\"cp\">}}</span><span class=\"s\">=</span><span class=\"cp\">{{</span> <span class=\"nv\">value</span> <span class=\"cp\">}}</span><span class=\"s\">&amp;amp;</span>\n<span class=\"s\">    </span><span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span>\n<span class=\"s\">  </span><span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span><span class=\"s\">page=</span><span class=\"cp\">{{</span> <span class=\"nv\">page.next_page_number</span> <span class=\"cp\">}}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span>Next page<span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>When switching to using this new template tag, the above magically becomes:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{%</span> <span class=\"k\">querystring</span> <span class=\"nv\">page</span><span class=\"o\">=</span><span class=\"nv\">page.next_page_number</span> <span class=\"cp\">%}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span>Next page<span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n</section>\n<section id=\"postgresql-connection-pools\">\n<h3>PostgreSQL Connection Pools<a class=\"heading-anchor\" href=\"#postgresql-connection-pools\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django 5.1 also introduces <a class=\"reference internal\" href=\"/en/dev/ref/databases/#postgresql-pool\"><span class=\"std std-ref\">connection pool</span></a> support for\nPostgreSQL. As the time to establish a new connection can be relatively long,\nkeeping connections open can reduce latency.</p>\n<p>To use a connection pool with <a class=\"reference external\" href=\"https://www.psycopg.org/\">psycopg</a>, you can set the <code class=\"docutils literal notranslate\">&quot;pool&quot;</code> option\ninside <a class=\"reference internal\" href=\"/en/dev/ref/settings/#std-setting-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\">OPTIONS</code></a> to be a dict to be passed to\n<a class=\"reference external\" href=\"https://www.psycopg.org/psycopg3/docs/api/pool.html#psycopg_pool.ConnectionPool\" title=\"(in psycopg)\"><code class=\"xref py py-class docutils literal notranslate\">ConnectionPool</code></a>, or to <code class=\"docutils literal notranslate\">True</code> to use the\n<code class=\"docutils literal notranslate\">ConnectionPool</code> defaults:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>DATABASES <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s2\">&quot;default&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;ENGINE&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.db.backends.postgresql&quot;</span><span class=\"p\">,</span>\n        <span class=\"c1\"># ...</span>\n        <span class=\"s2\">&quot;OPTIONS&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;pool&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n                <span class=\"s2\">&quot;min_size&quot;</span><span class=\"p\">:</span> <span class=\"mi\">2</span><span class=\"p\">,</span>\n                <span class=\"s2\">&quot;max_size&quot;</span><span class=\"p\">:</span> <span class=\"mi\">4</span><span class=\"p\">,</span>\n                <span class=\"s2\">&quot;timeout&quot;</span><span class=\"p\">:</span> <span class=\"mi\">10</span><span class=\"p\">,</span>\n            <span class=\"p\">}</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n</section>\n<section id=\"middleware-to-require-authentication-by-default\">\n<h3>Middleware to require authentication by default<a class=\"heading-anchor\" href=\"#middleware-to-require-authentication-by-default\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The new <a class=\"reference internal\" href=\"/en/dev/ref/middleware/#django.contrib.auth.middleware.LoginRequiredMiddleware\" title=\"django.contrib.auth.middleware.LoginRequiredMiddleware\"><code class=\"xref py py-class docutils literal notranslate\">LoginRequiredMiddleware</code></a>\nredirects all unauthenticated requests to a login page. Views can allow\nunauthenticated requests by using the new\n<a class=\"reference internal\" href=\"/en/dev/topics/auth/default/#django.contrib.auth.decorators.login_not_required\" title=\"django.contrib.auth.decorators.login_not_required\"><code class=\"xref py py-func docutils literal notranslate\">login_not_required()</code></a> decorator.</p>\n<p><code class=\"docutils literal notranslate\">LoginRequiredMiddleware</code> respects the <code class=\"docutils literal notranslate\">login_url</code> and\n<code class=\"docutils literal notranslate\">redirect_field_name</code> values set via the\n<a class=\"reference internal\" href=\"/en/dev/topics/auth/default/#django.contrib.auth.decorators.login_required\" title=\"django.contrib.auth.decorators.login_required\"><code class=\"xref py py-func docutils literal notranslate\">login_required()</code></a> decorator, but does not\nsupport setting <code class=\"docutils literal notranslate\">login_url</code> or <code class=\"docutils literal notranslate\">redirect_field_name</code> via the\n<a class=\"reference internal\" href=\"/en/dev/topics/auth/default/#django.contrib.auth.mixins.LoginRequiredMixin\" title=\"django.contrib.auth.mixins.LoginRequiredMixin\"><code class=\"xref py py-class docutils literal notranslate\">LoginRequiredMixin</code></a>.</p>\n<p>To enable this, add\n<code class=\"docutils literal notranslate\">&quot;django.contrib.auth.middleware.LoginRequiredMiddleware&quot;</code> to your\n<a class=\"reference internal\" href=\"/en/dev/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\">MIDDLEWARE</code></a> setting.</p>\n</section>\n<section id=\"minor-features\">\n<h3>Minor features<a class=\"heading-anchor\" href=\"#minor-features\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<section id=\"django-contrib-admin\">\n<h4><a class=\"reference internal\" href=\"/en/dev/ref/contrib/admin/#module-django.contrib.admin\" title=\"django.contrib.admin: Django's admin site.\"><code class=\"xref py py-mod docutils literal notranslate\">django.contrib.admin</code></a><a class=\"heading-anchor\" href=\"#django-contrib-admin\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display\" title=\"django.contrib.admin.ModelAdmin.list_display\"><code class=\"xref py py-attr docutils literal notranslate\">ModelAdmin.list_display</code></a> now supports using <code class=\"docutils literal notranslate\">__</code> lookups to list\nfields from related models.</p></li>\n</ul>\n</section>\n<section id=\"django-contrib-auth\">\n<h4><a class=\"reference internal\" href=\"/en/dev/topics/auth/#module-django.contrib.auth\" title=\"django.contrib.auth: Django's authentication framework.\"><code class=\"xref py py-mod docutils literal notranslate\">django.contrib.auth</code></a><a class=\"heading-anchor\" href=\"#django-contrib-auth\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<ul class=\"simple\">\n<li><p>The default iteration count for the PBKDF2 password hasher is increased from\n720,000 to 870,000.</p></li>\n<li><p>The default <code class=\"docutils literal notranslate\">parallelism</code> of the <code class=\"docutils literal notranslate\">ScryptPasswordHasher</code> is increased from\n1 to 5, to follow OWASP recommendations.</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/topics/auth/default/#django.contrib.auth.forms.AdminUserCreationForm\" title=\"django.contrib.auth.forms.AdminUserCreationForm\"><code class=\"xref py py-class docutils literal notranslate\">AdminUserCreationForm</code></a> and\nthe existing <a class=\"reference internal\" href=\"/en/dev/topics/auth/default/#django.contrib.auth.forms.AdminPasswordChangeForm\" title=\"django.contrib.auth.forms.AdminPasswordChangeForm\"><code class=\"xref py py-class docutils literal notranslate\">AdminPasswordChangeForm</code></a> now\nsupport disabling password-based authentication by setting an unusable\npassword on form save. This is now available in the admin when visiting the\nuser creation and password change pages.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/topics/auth/default/#django.contrib.auth.decorators.login_required\" title=\"django.contrib.auth.decorators.login_required\"><code class=\"xref py py-func docutils literal notranslate\">login_required()</code></a>,\n<a class=\"reference internal\" href=\"/en/dev/topics/auth/default/#django.contrib.auth.decorators.permission_required\" title=\"django.contrib.auth.decorators.permission_required\"><code class=\"xref py py-func docutils literal notranslate\">permission_required()</code></a>, and\n<a class=\"reference internal\" href=\"/en/dev/topics/auth/default/#django.contrib.auth.decorators.user_passes_test\" title=\"django.contrib.auth.decorators.user_passes_test\"><code class=\"xref py py-func docutils literal notranslate\">user_passes_test()</code></a> decorators now\nsupport wrapping asynchronous view functions.</p></li>\n<li><p><code class=\"docutils literal notranslate\">ReadOnlyPasswordHashWidget</code> now includes a button to reset the user’s\npassword, which replaces the link previously embedded in the\n<code class=\"docutils literal notranslate\">ReadOnlyPasswordHashField</code>’s help text, improving the overall\naccessibility of the\n<a class=\"reference internal\" href=\"/en/dev/topics/auth/default/#django.contrib.auth.forms.UserChangeForm\" title=\"django.contrib.auth.forms.UserChangeForm\"><code class=\"xref py py-class docutils literal notranslate\">UserChangeForm</code></a>.</p></li>\n</ul>\n</section>\n<section id=\"django-contrib-gis\">\n<h4><a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/#module-django.contrib.gis\" title=\"django.contrib.gis: Geographic Information System (GIS) extensions for Django\"><code class=\"xref py py-mod docutils literal notranslate\">django.contrib.gis</code></a><a class=\"heading-anchor\" href=\"#django-contrib-gis\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/functions/#django.contrib.gis.db.models.functions.BoundingCircle\" title=\"django.contrib.gis.db.models.functions.BoundingCircle\"><code class=\"xref py py-class docutils literal notranslate\">BoundingCircle</code></a> is now\nsupported on SpatiaLite 5.1+.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/geoquerysets/#django.contrib.gis.db.models.Collect\" title=\"django.contrib.gis.db.models.Collect\"><code class=\"xref py py-class docutils literal notranslate\">Collect</code></a> is now supported on MySQL\n8.0.24+.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/geoip2/#django.contrib.gis.geoip2.GeoIP2\" title=\"django.contrib.gis.geoip2.GeoIP2\"><code class=\"xref py py-class docutils literal notranslate\">GeoIP2</code></a> now allows querying using\n<a class=\"reference external\" href=\"https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv4Address\" title=\"(in Python v3.14)\"><code class=\"xref py py-class docutils literal notranslate\">ipaddress.IPv4Address</code></a> or <a class=\"reference external\" href=\"https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv6Address\" title=\"(in Python v3.14)\"><code class=\"xref py py-class docutils literal notranslate\">ipaddress.IPv6Address</code></a> objects.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/geoip2/#django.contrib.gis.geoip2.GeoIP2.country\" title=\"django.contrib.gis.geoip2.GeoIP2.country\"><code class=\"xref py py-meth docutils literal notranslate\">GeoIP2.country()</code></a> now exposes the <code class=\"docutils literal notranslate\">continent_code</code>,\n<code class=\"docutils literal notranslate\">continent_name</code>, and <code class=\"docutils literal notranslate\">is_in_european_union</code> values.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/geoip2/#django.contrib.gis.geoip2.GeoIP2.city\" title=\"django.contrib.gis.geoip2.GeoIP2.city\"><code class=\"xref py py-meth docutils literal notranslate\">GeoIP2.city()</code></a> now exposes the <code class=\"docutils literal notranslate\">accuracy_radius</code> and <code class=\"docutils literal notranslate\">region_name</code>\nvalues. In addition, the <code class=\"docutils literal notranslate\">dma_code</code> and <code class=\"docutils literal notranslate\">region</code> values are now exposed\nas <code class=\"docutils literal notranslate\">metro_code</code> and <code class=\"docutils literal notranslate\">region_code</code>, but the previous keys are also\nretained for backward compatibility.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/measure/#django.contrib.gis.measure.Area\" title=\"django.contrib.gis.measure.Area\"><code class=\"xref py py-class docutils literal notranslate\">Area</code></a> now supports the <code class=\"docutils literal notranslate\">ha</code> unit.</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/gdal/#django.contrib.gis.gdal.OGRGeometry.is_3d\" title=\"django.contrib.gis.gdal.OGRGeometry.is_3d\"><code class=\"xref py py-attr docutils literal notranslate\">OGRGeometry.is_3d</code></a> attribute allows checking if a geometry\nhas a <code class=\"docutils literal notranslate\">Z</code> coordinate dimension.</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/gdal/#django.contrib.gis.gdal.OGRGeometry.set_3d\" title=\"django.contrib.gis.gdal.OGRGeometry.set_3d\"><code class=\"xref py py-meth docutils literal notranslate\">OGRGeometry.set_3d()</code></a> method allows addition and removal of the\n<code class=\"docutils literal notranslate\">Z</code> coordinate dimension.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/gdal/#django.contrib.gis.gdal.OGRGeometry\" title=\"django.contrib.gis.gdal.OGRGeometry\"><code class=\"xref py py-class docutils literal notranslate\">OGRGeometry</code></a>,\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/gdal/#django.contrib.gis.gdal.Point\" title=\"django.contrib.gis.gdal.Point\"><code class=\"xref py py-class docutils literal notranslate\">Point</code></a>,\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/gdal/#django.contrib.gis.gdal.LineString\" title=\"django.contrib.gis.gdal.LineString\"><code class=\"xref py py-class docutils literal notranslate\">LineString</code></a>,\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/gdal/#django.contrib.gis.gdal.Polygon\" title=\"django.contrib.gis.gdal.Polygon\"><code class=\"xref py py-class docutils literal notranslate\">Polygon</code></a>, and\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/gdal/#django.contrib.gis.gdal.GeometryCollection\" title=\"django.contrib.gis.gdal.GeometryCollection\"><code class=\"xref py py-class docutils literal notranslate\">GeometryCollection</code></a> and its subclasses now\nsupport measured geometries via the new <a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/gdal/#django.contrib.gis.gdal.OGRGeometry.is_measured\" title=\"django.contrib.gis.gdal.OGRGeometry.is_measured\"><code class=\"xref py py-attr docutils literal notranslate\">OGRGeometry.is_measured</code></a> and\n<code class=\"docutils literal notranslate\">m</code> properties, and the <a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/gdal/#django.contrib.gis.gdal.OGRGeometry.set_measured\" title=\"django.contrib.gis.gdal.OGRGeometry.set_measured\"><code class=\"xref py py-meth docutils literal notranslate\">OGRGeometry.set_measured()</code></a> method.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/gdal/#django.contrib.gis.gdal.OGRGeometry.centroid\" title=\"django.contrib.gis.gdal.OGRGeometry.centroid\"><code class=\"xref py py-attr docutils literal notranslate\">OGRGeometry.centroid</code></a> is now available on all supported geometry\ntypes.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/functions/#django.contrib.gis.db.models.functions.FromWKB\" title=\"django.contrib.gis.db.models.functions.FromWKB\"><code class=\"xref py py-class docutils literal notranslate\">FromWKB()</code></a> and\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/functions/#django.contrib.gis.db.models.functions.FromWKT\" title=\"django.contrib.gis.db.models.functions.FromWKT\"><code class=\"xref py py-class docutils literal notranslate\">FromWKT()</code></a> functions\nnow support the optional <code class=\"docutils literal notranslate\">srid</code> argument (except for Oracle where it is\nignored).</p></li>\n</ul>\n</section>\n<section id=\"django-contrib-postgres\">\n<h4><a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/#module-django.contrib.postgres\" title=\"django.contrib.postgres: PostgreSQL-specific fields and features\"><code class=\"xref py py-mod docutils literal notranslate\">django.contrib.postgres</code></a><a class=\"heading-anchor\" href=\"#django-contrib-postgres\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/indexes/#django.contrib.postgres.indexes.BTreeIndex\" title=\"django.contrib.postgres.indexes.BTreeIndex\"><code class=\"xref py py-class docutils literal notranslate\">BTreeIndex</code></a> now supports the\n<code class=\"docutils literal notranslate\">deduplicate_items</code> parameter.</p></li>\n</ul>\n</section>\n<section id=\"django-contrib-sessions\">\n<h4><a class=\"reference internal\" href=\"/en/dev/topics/http/sessions/#module-django.contrib.sessions\" title=\"django.contrib.sessions: Provides session management for Django projects.\"><code class=\"xref py py-mod docutils literal notranslate\">django.contrib.sessions</code></a><a class=\"heading-anchor\" href=\"#django-contrib-sessions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/en/dev/topics/http/sessions/#django.contrib.sessions.backends.cached_db.SessionStore\" title=\"django.contrib.sessions.backends.cached_db.SessionStore\"><code class=\"xref py py-class docutils literal notranslate\">django.contrib.sessions.backends.cached_db.SessionStore</code></a> now handles\nexceptions when storing session information in the cache, logging proper\nerror messages with their traceback via the newly added\n<a class=\"reference internal\" href=\"/en/dev/ref/logging/#django-contrib-sessions-logger\"><span class=\"std std-ref\">sessions logger</span></a>.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/topics/http/sessions/#django.contrib.sessions.backends.base.SessionBase\" title=\"django.contrib.sessions.backends.base.SessionBase\"><code class=\"xref py py-class docutils literal notranslate\">django.contrib.sessions.backends.base.SessionBase</code></a> and all built-in\nsession engines now provide async API. The new asynchronous methods all have\n<code class=\"docutils literal notranslate\">a</code> prefixed names, e.g. <code class=\"docutils literal notranslate\">aget()</code>, <code class=\"docutils literal notranslate\">akeys()</code>, or <code class=\"docutils literal notranslate\">acycle_key()</code>.</p></li>\n</ul>\n</section>\n<section id=\"database-backends\">\n<h4>Database backends<a class=\"heading-anchor\" href=\"#database-backends\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\">&quot;init_command&quot;</code> option is now supported in <a class=\"reference internal\" href=\"/en/dev/ref/settings/#std-setting-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\">OPTIONS</code></a> on SQLite\nto allow specifying <a class=\"reference internal\" href=\"/en/dev/ref/databases/#sqlite-init-command\"><span class=\"std std-ref\">pragma options</span></a> to set upon\nconnection.</p></li>\n<li><p><code class=\"docutils literal notranslate\">&quot;transaction_mode&quot;</code> option is now supported in <a class=\"reference internal\" href=\"/en/dev/ref/settings/#std-setting-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\">OPTIONS</code></a> on\nSQLite to allow specifying the <a class=\"reference internal\" href=\"/en/dev/ref/databases/#sqlite-transaction-behavior\"><span class=\"std std-ref\">Transactions behavior</span></a>.</p></li>\n<li><p><code class=\"docutils literal notranslate\">&quot;pool&quot;</code> option is now supported in <a class=\"reference internal\" href=\"/en/dev/ref/settings/#std-setting-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\">OPTIONS</code></a> on PostgreSQL to\nallow using <a class=\"reference internal\" href=\"/en/dev/ref/databases/#postgresql-pool\"><span class=\"std std-ref\">connection pools</span></a>.</p></li>\n</ul>\n</section>\n<section id=\"error-reporting\">\n<h4>Error Reporting<a class=\"heading-anchor\" href=\"#error-reporting\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<ul class=\"simple\">\n<li><p>In order to improve accessibility, the technical 404 and 500 error pages now\nuse HTML landmark elements for the header, footer, and main content areas.</p></li>\n</ul>\n</section>\n<section id=\"file-storage\">\n<h4>File Storage<a class=\"heading-anchor\" href=\"#file-storage\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<ul class=\"simple\">\n<li><p>The <a class=\"reference internal\" href=\"/en/dev/ref/files/storage/#django.core.files.storage.FileSystemStorage.allow_overwrite\" title=\"django.core.files.storage.FileSystemStorage.allow_overwrite\"><code class=\"xref py py-attr docutils literal notranslate\">allow_overwrite</code></a>\nparameter of <a class=\"reference internal\" href=\"/en/dev/ref/files/storage/#django.core.files.storage.FileSystemStorage\" title=\"django.core.files.storage.FileSystemStorage\"><code class=\"xref py py-class docutils literal notranslate\">FileSystemStorage</code></a> now allows\nsaving new files over existing ones.</p></li>\n</ul>\n</section>\n<section id=\"forms\">\n<h4>Forms<a class=\"heading-anchor\" href=\"#forms\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<ul class=\"simple\">\n<li><p>In order to improve accessibility and enable screen readers to associate\nfieldsets with their help text, the form fieldset now includes the\n<code class=\"docutils literal notranslate\">aria-describedby</code> HTML attribute.</p></li>\n</ul>\n</section>\n<section id=\"management-commands\">\n<h4>Management Commands<a class=\"heading-anchor\" href=\"#management-commands\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<ul class=\"simple\">\n<li><p>The <a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#django-admin-makemigrations\"><code class=\"xref std std-djadmin docutils literal notranslate\">makemigrations</code></a> command now displays meaningful symbols for\neach operation to highlight <a class=\"reference internal\" href=\"/en/dev/ref/migration-operations/#django.db.migrations.operations.base.OperationCategory\" title=\"django.db.migrations.operations.base.OperationCategory\"><code class=\"xref py py-class docutils literal notranslate\">operation categories</code></a>.</p></li>\n</ul>\n</section>\n<section id=\"migrations\">\n<h4>Migrations<a class=\"heading-anchor\" href=\"#migrations\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<ul class=\"simple\">\n<li><p>The new <code class=\"docutils literal notranslate\">Operation.category</code> attribute allows specifying an\n<a class=\"reference internal\" href=\"/en/dev/ref/migration-operations/#django.db.migrations.operations.base.OperationCategory\" title=\"django.db.migrations.operations.base.OperationCategory\"><code class=\"xref py py-class docutils literal notranslate\">operation category</code></a> used by the\n<a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#django-admin-makemigrations\"><code class=\"xref std std-djadmin docutils literal notranslate\">makemigrations</code></a> to display a meaningful symbol for the operation.</p></li>\n</ul>\n</section>\n<section id=\"models\">\n<h4>Models<a class=\"heading-anchor\" href=\"#models\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.explain\" title=\"django.db.models.query.QuerySet.explain\"><code class=\"xref py py-meth docutils literal notranslate\">QuerySet.explain()</code></a> now supports the <code class=\"docutils literal notranslate\">generic_plan</code> option on\nPostgreSQL 16+.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/models/expressions/#django.db.models.expressions.RowRange\" title=\"django.db.models.expressions.RowRange\"><code class=\"xref py py-class docutils literal notranslate\">RowRange</code></a> now accepts positive integers\nfor the <code class=\"docutils literal notranslate\">start</code> argument and negative integers for the <code class=\"docutils literal notranslate\">end</code> argument.</p></li>\n<li><p>The new <code class=\"docutils literal notranslate\">exclusion</code> argument of\n<a class=\"reference internal\" href=\"/en/dev/ref/models/expressions/#django.db.models.expressions.RowRange\" title=\"django.db.models.expressions.RowRange\"><code class=\"xref py py-class docutils literal notranslate\">RowRange</code></a> and\n<a class=\"reference internal\" href=\"/en/dev/ref/models/expressions/#django.db.models.expressions.ValueRange\" title=\"django.db.models.expressions.ValueRange\"><code class=\"xref py py-class docutils literal notranslate\">ValueRange</code></a> allows excluding rows,\ngroups, and ties from the window frames.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.order_by\" title=\"django.db.models.query.QuerySet.order_by\"><code class=\"xref py py-meth docutils literal notranslate\">QuerySet.order_by()</code></a> now supports ordering by annotation transforms\nsuch as <code class=\"docutils literal notranslate\">JSONObject</code> keys and <code class=\"docutils literal notranslate\">ArrayAgg</code> indices.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/models/expressions/#django.db.models.F\" title=\"django.db.models.F\"><code class=\"xref py py-class docutils literal notranslate\">F()</code></a> and <a class=\"reference internal\" href=\"/en/dev/ref/models/expressions/#django.db.models.OuterRef\" title=\"django.db.models.OuterRef\"><code class=\"xref py py-class docutils literal notranslate\">OuterRef()</code></a> expressions that output\n<a class=\"reference internal\" href=\"/en/dev/ref/models/fields/#django.db.models.CharField\" title=\"django.db.models.CharField\"><code class=\"xref py py-class docutils literal notranslate\">CharField</code></a>, <a class=\"reference internal\" href=\"/en/dev/ref/models/fields/#django.db.models.EmailField\" title=\"django.db.models.EmailField\"><code class=\"xref py py-class docutils literal notranslate\">EmailField</code></a>,\n<a class=\"reference internal\" href=\"/en/dev/ref/models/fields/#django.db.models.SlugField\" title=\"django.db.models.SlugField\"><code class=\"xref py py-class docutils literal notranslate\">SlugField</code></a>, <a class=\"reference internal\" href=\"/en/dev/ref/models/fields/#django.db.models.URLField\" title=\"django.db.models.URLField\"><code class=\"xref py py-class docutils literal notranslate\">URLField</code></a>,\n<a class=\"reference internal\" href=\"/en/dev/ref/models/fields/#django.db.models.TextField\" title=\"django.db.models.TextField\"><code class=\"xref py py-class docutils literal notranslate\">TextField</code></a>, or\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/fields/#django.contrib.postgres.fields.ArrayField\" title=\"django.contrib.postgres.fields.ArrayField\"><code class=\"xref py py-class docutils literal notranslate\">ArrayField</code></a> can now be <a class=\"reference internal\" href=\"/en/dev/ref/models/expressions/#slicing-using-f\"><span class=\"std std-ref\">sliced</span></a>.</p></li>\n<li><p>The new <code class=\"docutils literal notranslate\">from_queryset</code> argument of <a class=\"reference internal\" href=\"/en/dev/ref/models/instances/#django.db.models.Model.refresh_from_db\" title=\"django.db.models.Model.refresh_from_db\"><code class=\"xref py py-meth docutils literal notranslate\">Model.refresh_from_db()</code></a> and\n<a class=\"reference internal\" href=\"/en/dev/ref/models/instances/#django.db.models.Model.arefresh_from_db\" title=\"django.db.models.Model.arefresh_from_db\"><code class=\"xref py py-meth docutils literal notranslate\">Model.arefresh_from_db()</code></a>  allows customizing the queryset used to\nreload a model’s value. This can be used to lock the row before reloading or\nto select related objects.</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/ref/models/expressions/#django.db.models.Expression.constraint_validation_compatible\" title=\"django.db.models.Expression.constraint_validation_compatible\"><code class=\"xref py py-attr docutils literal notranslate\">Expression.constraint_validation_compatible</code></a> attribute allows\nspecifying that the expression should be ignored during a constraint\nvalidation.</p></li>\n</ul>\n</section>\n<section id=\"templates\">\n<h4>Templates<a class=\"heading-anchor\" href=\"#templates\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<ul class=\"simple\">\n<li><p>Custom tags may now set extra data on the <code class=\"docutils literal notranslate\">Parser</code> object that will later\nbe made available on the <code class=\"docutils literal notranslate\">Template</code> instance. Such data may be used, for\nexample, by the template loader, or other template clients.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/topics/checks/#field-checking\"><span class=\"std std-ref\">Template engines</span></a> now implement a <code class=\"docutils literal notranslate\">check()</code> method\nthat is already registered with the check framework.</p></li>\n</ul>\n</section>\n<section id=\"tests\">\n<h4>Tests<a class=\"heading-anchor\" href=\"#tests\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<ul>\n<li><p><a class=\"reference internal\" href=\"/en/dev/topics/testing/tools/#django.test.SimpleTestCase.assertContains\" title=\"django.test.SimpleTestCase.assertContains\"><code class=\"xref py py-meth docutils literal notranslate\">assertContains()</code></a>,\n<a class=\"reference internal\" href=\"/en/dev/topics/testing/tools/#django.test.SimpleTestCase.assertNotContains\" title=\"django.test.SimpleTestCase.assertNotContains\"><code class=\"xref py py-meth docutils literal notranslate\">assertNotContains()</code></a>, and\n<a class=\"reference internal\" href=\"/en/dev/topics/testing/tools/#django.test.SimpleTestCase.assertInHTML\" title=\"django.test.SimpleTestCase.assertInHTML\"><code class=\"xref py py-meth docutils literal notranslate\">assertInHTML()</code></a> assertions now add haystacks\nto assertion error messages.</p></li>\n<li><p>The <a class=\"reference internal\" href=\"/en/dev/topics/testing/advanced/#django.test.RequestFactory\" title=\"django.test.RequestFactory\"><code class=\"xref py py-class docutils literal notranslate\">RequestFactory</code></a>,\n<a class=\"reference internal\" href=\"/en/dev/topics/testing/advanced/#django.test.AsyncRequestFactory\" title=\"django.test.AsyncRequestFactory\"><code class=\"xref py py-class docutils literal notranslate\">AsyncRequestFactory</code></a>, <a class=\"reference internal\" href=\"/en/dev/topics/testing/tools/#django.test.Client\" title=\"django.test.Client\"><code class=\"xref py py-class docutils literal notranslate\">Client</code></a>, and\n<a class=\"reference internal\" href=\"/en/dev/topics/testing/tools/#django.test.AsyncClient\" title=\"django.test.AsyncClient\"><code class=\"xref py py-class docutils literal notranslate\">AsyncClient</code></a> classes now support the <code class=\"docutils literal notranslate\">query_params</code>\nparameter, which accepts a dictionary of query string keys and values. This\nallows setting query strings on any HTTP methods more easily.</p>\n<div class=\"code-block\" data-language=\"python\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"bp\">self</span><span class=\"o\">.</span>client<span class=\"o\">.</span>post<span class=\"p\">(</span><span class=\"s2\">&quot;/items/1&quot;</span><span class=\"p\">,</span> query_params<span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;action&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;delete&quot;</span><span class=\"p\">})</span>\n<span class=\"k\">await</span> <span class=\"bp\">self</span><span class=\"o\">.</span>async_client<span class=\"o\">.</span>post<span class=\"p\">(</span><span class=\"s2\">&quot;/items/1&quot;</span><span class=\"p\">,</span> query_params<span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;action&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;delete&quot;</span><span class=\"p\">})</span>\n</code></pre></div>\n</li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/topics/testing/tools/#django.test.SimpleTestCase.assertNotInHTML\" title=\"django.test.SimpleTestCase.assertNotInHTML\"><code class=\"xref py py-meth docutils literal notranslate\">SimpleTestCase.assertNotInHTML()</code></a> assertion allows testing that\nan HTML fragment is not contained in the given HTML haystack.</p></li>\n<li><p>In order to enforce test isolation, database connections inside threads are\nno longer allowed in <a class=\"reference internal\" href=\"/en/dev/topics/testing/tools/#django.test.SimpleTestCase\" title=\"django.test.SimpleTestCase\"><code class=\"xref py py-class docutils literal notranslate\">SimpleTestCase</code></a>.</p></li>\n</ul>\n</section>\n<section id=\"validators\">\n<h4>Validators<a class=\"heading-anchor\" href=\"#validators\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<ul class=\"simple\">\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/ref/validators/#django.core.validators.DomainNameValidator\" title=\"django.core.validators.DomainNameValidator\"><code class=\"xref py py-class docutils literal notranslate\">DomainNameValidator</code></a> validates domain\nnames, including internationalized domain names. The new\n<a class=\"reference internal\" href=\"/en/dev/ref/validators/#django.core.validators.validate_domain_name\" title=\"django.core.validators.validate_domain_name\"><code class=\"xref py py-func docutils literal notranslate\">validate_domain_name()</code></a> function returns an\ninstance of <a class=\"reference internal\" href=\"/en/dev/ref/validators/#django.core.validators.DomainNameValidator\" title=\"django.core.validators.DomainNameValidator\"><code class=\"xref py py-class docutils literal notranslate\">DomainNameValidator</code></a>.</p></li>\n</ul>\n</section>\n</section>\n</section>\n<section id=\"backwards-incompatible-changes-in-5-1\">\n<span id=\"backwards-incompatible-5-1\"></span><h2>Backwards incompatible changes in 5.1<a class=\"heading-anchor\" href=\"#backwards-incompatible-changes-in-5-1\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"id1\">\n<h3><a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/#module-django.contrib.gis\" title=\"django.contrib.gis: Geographic Information System (GIS) extensions for Django\"><code class=\"xref py py-mod docutils literal notranslate\">django.contrib.gis</code></a><a class=\"heading-anchor\" href=\"#id1\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<ul class=\"simple\">\n<li><p>Support for PostGIS 2.5 is removed.</p></li>\n<li><p>Support for PROJ &lt; 6 is removed.</p></li>\n<li><p>Support for GDAL 2.4 is removed.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/geoip2/#django.contrib.gis.geoip2.GeoIP2\" title=\"django.contrib.gis.geoip2.GeoIP2\"><code class=\"xref py py-class docutils literal notranslate\">GeoIP2</code></a> no longer opens both city and\ncountry databases when a directory path is provided, preferring the city\ndatabase, if it is available. The country database is a subset of the city\ndatabase and both are not typically needed. If you require use of the country\ndatabase when in the same directory as the city database, explicitly pass the\ncountry database path to the constructor.</p></li>\n</ul>\n</section>\n<section id=\"dropped-support-for-mariadb-10-4\">\n<h3>Dropped support for MariaDB 10.4<a class=\"heading-anchor\" href=\"#dropped-support-for-mariadb-10-4\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Upstream support for MariaDB 10.4 ends in June 2024. Django 5.1 supports\nMariaDB 10.5 and higher.</p>\n</section>\n<section id=\"dropped-support-for-postgresql-12\">\n<h3>Dropped support for PostgreSQL 12<a class=\"heading-anchor\" href=\"#dropped-support-for-postgresql-12\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Upstream support for PostgreSQL 12 ends in November 2024. Django 5.1 supports\nPostgreSQL 13 and higher.</p>\n</section>\n<section id=\"miscellaneous\">\n<h3>Miscellaneous<a class=\"heading-anchor\" href=\"#miscellaneous\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<ul class=\"simple\">\n<li><p>In order to improve accessibility, the admin’s changelist filter is now\nrendered in a <code class=\"docutils literal notranslate\">&lt;nav&gt;</code> tag instead of a <code class=\"docutils literal notranslate\">&lt;div&gt;</code>.</p></li>\n<li><p>In order to improve accessibility, the admin’s footer is now rendered in\na <code class=\"docutils literal notranslate\">&lt;footer&gt;</code> tag instead of a <code class=\"docutils literal notranslate\">&lt;div&gt;</code>, and also moved below the\n<code class=\"docutils literal notranslate\">&lt;div id=&quot;main&quot;&gt;</code> element.</p></li>\n<li><p>In order to improve accessibility, the expandable widget used for\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.fieldsets\" title=\"django.contrib.admin.ModelAdmin.fieldsets\"><code class=\"xref py py-attr docutils literal notranslate\">ModelAdmin.fieldsets</code></a> and\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/admin/#django.contrib.admin.InlineModelAdmin\" title=\"django.contrib.admin.InlineModelAdmin\"><code class=\"xref py py-attr docutils literal notranslate\">InlineModelAdmin.fieldsets</code></a>,\nwhen the fieldset has a name and use the <code class=\"docutils literal notranslate\">collapse</code> class, now includes\n<code class=\"docutils literal notranslate\">&lt;details&gt;</code> and <code class=\"docutils literal notranslate\">&lt;summary&gt;</code> elements.</p></li>\n<li><p>The JavaScript file <code class=\"docutils literal notranslate\">collapse.js</code> is removed since it is no longer needed\nin the Django admin site.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/topics/testing/tools/#django.test.SimpleTestCase.assertURLEqual\" title=\"django.test.SimpleTestCase.assertURLEqual\"><code class=\"xref py py-meth docutils literal notranslate\">SimpleTestCase.assertURLEqual()</code></a> and\n<a class=\"reference internal\" href=\"/en/dev/topics/testing/tools/#django.test.SimpleTestCase.assertInHTML\" title=\"django.test.SimpleTestCase.assertInHTML\"><code class=\"xref py py-meth docutils literal notranslate\">assertInHTML()</code></a> now add <code class=\"docutils literal notranslate\">&quot;: &quot;</code> to the\n<code class=\"docutils literal notranslate\">msg_prefix</code>. This is consistent with the behavior of other assertions.</p></li>\n<li><p><code class=\"docutils literal notranslate\">django.utils.text.Truncator</code> used by <a class=\"reference internal\" href=\"/en/dev/ref/templates/builtins/#std-templatefilter-truncatechars_html\"><code class=\"xref std std-tfilter docutils literal notranslate\">truncatechars_html</code></a> and\n<a class=\"reference internal\" href=\"/en/dev/ref/templates/builtins/#std-templatefilter-truncatewords_html\"><code class=\"xref std std-tfilter docutils literal notranslate\">truncatewords_html</code></a> template filters now uses\n<a class=\"reference external\" href=\"https://docs.python.org/3/library/html.parser.html#html.parser.HTMLParser\" title=\"(in Python v3.14)\"><code class=\"xref py py-class docutils literal notranslate\">html.parser.HTMLParser</code></a> subclasses. This results in a more robust\nand faster operation, but there may be small differences in the output.</p></li>\n<li><p>The undocumented <code class=\"docutils literal notranslate\">django.urls.converters.get_converter()</code> function is\nremoved.</p></li>\n<li><p>The minimum supported version of SQLite is increased from 3.27.0 to 3.31.0.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/models/fields/#django.db.models.FileField\" title=\"django.db.models.FileField\"><code class=\"xref py py-class docutils literal notranslate\">FileField</code></a> now raises a\n<a class=\"reference internal\" href=\"/en/dev/ref/exceptions/#django.core.exceptions.FieldError\" title=\"django.core.exceptions.FieldError\"><code class=\"xref py py-class docutils literal notranslate\">FieldError</code></a> when saving a file without a\n<code class=\"docutils literal notranslate\">name</code>.</p></li>\n<li><p><code class=\"docutils literal notranslate\">ImageField.update_dimension_fields(force=True)</code> is no longer called after\nsaving the image to storage. If your storage backend resizes images, the\n<code class=\"docutils literal notranslate\">width_field</code> and <code class=\"docutils literal notranslate\">height_field</code> will not match the width and height of\nthe image.</p></li>\n<li><p>The minimum supported version of <code class=\"docutils literal notranslate\">asgiref</code> is increased from 3.7.0 to\n3.8.1.</p></li>\n<li><p>To improve performance, the <code class=\"docutils literal notranslate\">delete_selected</code> admin action now uses\n<code class=\"docutils literal notranslate\">QuerySet.bulk_create()</code> when creating multiple <code class=\"docutils literal notranslate\">LogEntry</code> objects. As a\nresult, <code class=\"docutils literal notranslate\">pre_save</code> and <code class=\"docutils literal notranslate\">post_save</code> signals for <code class=\"docutils literal notranslate\">LogEntry</code> are not sent\nwhen multiple objects are deleted via this admin action.</p></li>\n</ul>\n</section>\n</section>\n<section id=\"features-deprecated-in-5-1\">\n<span id=\"deprecated-features-5-1\"></span><h2>Features deprecated in 5.1<a class=\"heading-anchor\" href=\"#features-deprecated-in-5-1\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"id2\">\n<h3>Miscellaneous<a class=\"heading-anchor\" href=\"#id2\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<ul class=\"simple\">\n<li><p>The <code class=\"docutils literal notranslate\">ModelAdmin.log_deletion()</code> and <code class=\"docutils literal notranslate\">LogEntryManager.log_action()</code>\nmethods are deprecated. Subclasses should implement\n<code class=\"docutils literal notranslate\">ModelAdmin.log_deletions()</code> and  <code class=\"docutils literal notranslate\">LogEntryManager.log_actions()</code>\ninstead.</p></li>\n<li><p>The undocumented <code class=\"docutils literal notranslate\">django.utils.itercompat.is_iterable()</code> function and the\n<code class=\"docutils literal notranslate\">django.utils.itercompat</code> module are deprecated. Use\n<code class=\"docutils literal notranslate\">isinstance(..., collections.abc.Iterable)</code> instead.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">django.contrib.gis.geoip2.GeoIP2.coords()</code> method is deprecated. Use\n<code class=\"docutils literal notranslate\">django.contrib.gis.geoip2.GeoIP2.lon_lat()</code> instead.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">django.contrib.gis.geoip2.GeoIP2.open()</code> method is deprecated. Use the\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/geoip2/#django.contrib.gis.geoip2.GeoIP2\" title=\"django.contrib.gis.geoip2.GeoIP2\"><code class=\"xref py py-class docutils literal notranslate\">GeoIP2</code></a> constructor instead.</p></li>\n<li><p>Passing positional arguments to <a class=\"reference internal\" href=\"/en/dev/ref/models/instances/#django.db.models.Model.save\" title=\"django.db.models.Model.save\"><code class=\"xref py py-meth docutils literal notranslate\">Model.save()</code></a> and <a class=\"reference internal\" href=\"/en/dev/ref/models/instances/#django.db.models.Model.asave\" title=\"django.db.models.Model.asave\"><code class=\"xref py py-meth docutils literal notranslate\">Model.asave()</code></a>\nis deprecated in favor of keyword-only arguments.</p></li>\n<li><p>Setting <code class=\"docutils literal notranslate\">django.contrib.gis.gdal.OGRGeometry.coord_dim</code> is deprecated. Use\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/gdal/#django.contrib.gis.gdal.OGRGeometry.set_3d\" title=\"django.contrib.gis.gdal.OGRGeometry.set_3d\"><code class=\"xref py py-meth docutils literal notranslate\">set_3d()</code></a> instead.</p></li>\n<li><p>Overriding existing converters with <code class=\"docutils literal notranslate\">django.urls.register_converter()</code> is\ndeprecated.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">check</code> keyword argument of <code class=\"docutils literal notranslate\">CheckConstraint</code> is deprecated in favor\nof <code class=\"docutils literal notranslate\">condition</code>.</p></li>\n<li><p>The undocumented <code class=\"docutils literal notranslate\">OS_OPEN_FLAGS</code> property of\n<a class=\"reference internal\" href=\"/en/dev/ref/files/storage/#django.core.files.storage.FileSystemStorage\" title=\"django.core.files.storage.FileSystemStorage\"><code class=\"xref py py-class docutils literal notranslate\">FileSystemStorage</code></a> is deprecated. To allow\noverwriting files in storage, set the new\n<a class=\"reference internal\" href=\"/en/dev/ref/files/storage/#django.core.files.storage.FileSystemStorage.allow_overwrite\" title=\"django.core.files.storage.FileSystemStorage.allow_overwrite\"><code class=\"xref py py-attr docutils literal notranslate\">allow_overwrite</code></a> option\nto <code class=\"docutils literal notranslate\">True</code> instead.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">get_cache_name()</code> method of <code class=\"docutils literal notranslate\">FieldCacheMixin</code> is deprecated in favor\nof the <code class=\"docutils literal notranslate\">cache_name</code> cached property.</p></li>\n</ul>\n</section>\n</section>\n<section id=\"features-removed-in-5-1\">\n<h2>Features removed in 5.1<a class=\"heading-anchor\" href=\"#features-removed-in-5-1\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>These features have reached the end of their deprecation cycle and are removed\nin Django 5.1.</p>\n<p>See <a class=\"reference internal\" href=\"/en/dev/releases/4.2/#deprecated-features-4-2\"><span class=\"std std-ref\">Features deprecated in 4.2</span></a> for details on these changes, including how\nto remove usage of these features.</p>\n<ul class=\"simple\">\n<li><p>The <code class=\"docutils literal notranslate\">BaseUserManager.make_random_password()</code> method is removed.</p></li>\n<li><p>The model’s <code class=\"docutils literal notranslate\">Meta.index_together</code> option is removed.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">length_is</code> template filter is removed.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">django.contrib.auth.hashers.SHA1PasswordHasher</code>,\n<code class=\"docutils literal notranslate\">django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher</code>, and\n<code class=\"docutils literal notranslate\">django.contrib.auth.hashers.UnsaltedMD5PasswordHasher</code> are removed.</p></li>\n<li><p>The model <code class=\"docutils literal notranslate\">django.contrib.postgres.fields.CICharField</code>,\n<code class=\"docutils literal notranslate\">django.contrib.postgres.fields.CIEmailField</code>, and\n<code class=\"docutils literal notranslate\">django.contrib.postgres.fields.CITextField</code> are removed, except for\nsupport in historical migrations.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">django.contrib.postgres.fields.CIText</code> mixin is removed.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">map_width</code> and <code class=\"docutils literal notranslate\">map_height</code> attributes of <code class=\"docutils literal notranslate\">BaseGeometryWidget</code> are\nremoved.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">SimpleTestCase.assertFormsetError()</code> method is removed.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">TransactionTestCase.assertQuerysetEqual()</code> method is removed.</p></li>\n<li><p>Support for passing encoded JSON string literals to <code class=\"docutils literal notranslate\">JSONField</code> and\nassociated lookups and expressions is removed.</p></li>\n<li><p>Support for passing positional arguments to <code class=\"docutils literal notranslate\">Signer</code> and\n<code class=\"docutils literal notranslate\">TimestampSigner</code> is removed.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">DEFAULT_FILE_STORAGE</code> and <code class=\"docutils literal notranslate\">STATICFILES_STORAGE</code> settings is removed.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">django.core.files.storage.get_storage_class()</code> function is removed.</p></li>\n</ul>\n</section>","rootId":"django-5-1-release-notes","toc":[{"title":"Python compatibility","anchor":"python-compatibility","children":[]},{"title":"What’s new in Django 5.1","anchor":"what-s-new-in-django-5-1","children":[{"title":"{% querystring %} template tag","anchor":"querystring-template-tag","children":[]},{"title":"PostgreSQL Connection Pools","anchor":"postgresql-connection-pools","children":[]},{"title":"Middleware to require authentication by default","anchor":"middleware-to-require-authentication-by-default","children":[]},{"title":"Minor features","anchor":"minor-features","children":[{"title":"django.contrib.admin","anchor":"django-contrib-admin","children":[]},{"title":"django.contrib.auth","anchor":"django-contrib-auth","children":[]},{"title":"django.contrib.gis","anchor":"django-contrib-gis","children":[]},{"title":"django.contrib.postgres","anchor":"django-contrib-postgres","children":[]},{"title":"django.contrib.sessions","anchor":"django-contrib-sessions","children":[]},{"title":"Database backends","anchor":"database-backends","children":[]},{"title":"Error Reporting","anchor":"error-reporting","children":[]},{"title":"File Storage","anchor":"file-storage","children":[]},{"title":"Forms","anchor":"forms","children":[]},{"title":"Management Commands","anchor":"management-commands","children":[]},{"title":"Migrations","anchor":"migrations","children":[]},{"title":"Models","anchor":"models","children":[]},{"title":"Templates","anchor":"templates","children":[]},{"title":"Tests","anchor":"tests","children":[]},{"title":"Validators","anchor":"validators","children":[]}]}]},{"title":"Backwards incompatible changes in 5.1","anchor":"backwards-incompatible-changes-in-5-1","children":[{"title":"django.contrib.gis","anchor":"id1","children":[]},{"title":"Dropped support for MariaDB 10.4","anchor":"dropped-support-for-mariadb-10-4","children":[]},{"title":"Dropped support for PostgreSQL 12","anchor":"dropped-support-for-postgresql-12","children":[]},{"title":"Miscellaneous","anchor":"miscellaneous","children":[]}]},{"title":"Features deprecated in 5.1","anchor":"features-deprecated-in-5-1","children":[{"title":"Miscellaneous","anchor":"id2","children":[]}]},{"title":"Features removed in 5.1","anchor":"features-removed-in-5-1","children":[]}],"breadcrumbs":[{"docname":"releases/index","title":"Release notes","url":"/en/dev/releases/"}],"prev":{"docname":"releases/5.1.1","title":"Django 5.1.1 release notes","url":"/en/dev/releases/5.1.1/"},"next":{"docname":"releases/5.0.14","title":"Django 5.0.14 release notes","url":"/en/dev/releases/5.0.14/"},"formats":{"html":"/en/dev/releases/5.1/","markdown":"/en/dev/releases/5.1.md","json":"/en/dev/releases/5.1.json"},"source":"https://github.com/django/django/blob/main/docs/releases/5.1.txt","official":"https://docs.djangoproject.com/en/dev/releases/5.1/","inVersions":["dev","6.1","6.0","5.2","5.1"],"inLocales":["en"]}