{"title":"Django 4.1 release notes","version":"dev","locale":"en","docname":"releases/4.1","url":"/en/dev/releases/4.1/","canonical":"https://djangodocs.dev/en/dev/releases/4.1/","summary":"Welcome to Django 4.1! These release notes cover the new features, as well as some backwards incompatible changes you’ll want to be aware of when upgrading…","html":"<h1>Django 4.1 release notes<a class=\"heading-anchor\" href=\"#django-4-1-release-notes\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p><em>August 3, 2022</em></p>\n<p>Welcome to Django 4.1!</p>\n<p>These release notes cover the <a class=\"reference internal\" href=\"#whats-new-4-1\"><span class=\"std std-ref\">new features</span></a>, as well as\nsome <a class=\"reference internal\" href=\"#backwards-incompatible-4-1\"><span class=\"std std-ref\">backwards incompatible changes</span></a> you’ll\nwant to be aware of when upgrading from Django 4.0 or earlier. We’ve\n<a class=\"reference internal\" href=\"#deprecated-features-4-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 4.1 supports Python 3.8, 3.9, 3.10, and 3.11 (as of 4.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-4-1\">\n<span id=\"whats-new-4-1\"></span><h2>What’s new in Django 4.1<a class=\"heading-anchor\" href=\"#what-s-new-in-django-4-1\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"asynchronous-handlers-for-class-based-views\">\n<h3>Asynchronous handlers for class-based views<a class=\"heading-anchor\" href=\"#asynchronous-handlers-for-class-based-views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>View subclasses may now define async HTTP method handlers:</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><span class=\"kn\">import</span> <span class=\"nn\">asyncio</span>\n<span class=\"kn\">from</span> <span class=\"nn\">django.http</span> <span class=\"kn\">import</span> HttpResponse\n<span class=\"kn\">from</span> <span class=\"nn\">django.views</span> <span class=\"kn\">import</span> View\n\n\n<span class=\"k\">class</span> <span class=\"nc\">AsyncView</span><span class=\"p\">(</span>View<span class=\"p\">):</span>\n    <span class=\"k\">async</span> <span class=\"k\">def</span> <span class=\"nf\">get</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> request<span class=\"p\">,</span> <span class=\"o\">*</span>args<span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">):</span>\n        <span class=\"c1\"># Perform view logic using await.</span>\n        <span class=\"k\">await</span> asyncio<span class=\"o\">.</span>sleep<span class=\"p\">(</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n        <span class=\"k\">return</span> HttpResponse<span class=\"p\">(</span><span class=\"s2\">&quot;Hello async world!&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>See <a class=\"reference internal\" href=\"/en/dev/topics/class-based-views/#async-class-based-views\"><span class=\"std std-ref\">Asynchronous class-based views</span></a> for more details.</p>\n</section>\n<section id=\"asynchronous-orm-interface\">\n<h3>Asynchronous ORM interface<a class=\"heading-anchor\" href=\"#asynchronous-orm-interface\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><code class=\"docutils literal notranslate\">QuerySet</code> now provides an asynchronous interface for all data access\noperations. These are named as-per the existing synchronous operations but with\nan <code class=\"docutils literal notranslate\">a</code> prefix, for example <code class=\"docutils literal notranslate\">acreate()</code>, <code class=\"docutils literal notranslate\">aget()</code>, and so on.</p>\n<p>The new interface allows you to write asynchronous code without needing to wrap\nORM operations in <code class=\"docutils literal notranslate\">sync_to_async()</code>:</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><span class=\"k\">async</span> <span class=\"k\">for</span> author <span class=\"ow\">in</span> Author<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>name__startswith<span class=\"o\">=</span><span class=\"s2\">&quot;A&quot;</span><span class=\"p\">):</span>\n    book <span class=\"o\">=</span> <span class=\"k\">await</span> author<span class=\"o\">.</span>books<span class=\"o\">.</span>afirst<span class=\"p\">()</span>\n</code></pre></div>\n<p>Note that, at this stage, the underlying database operations remain\nsynchronous, with contributions ongoing to push asynchronous support down into\nthe SQL compiler, and integrate asynchronous database drivers. The new\nasynchronous queryset interface currently encapsulates the necessary\n<code class=\"docutils literal notranslate\">sync_to_async()</code> operations for you, and will allow your code to take\nadvantage of developments in the ORM’s asynchronous support as it evolves.</p>\n<p>See <a class=\"reference internal\" href=\"/en/dev/topics/db/queries/#async-queries\"><span class=\"std std-ref\">Asynchronous queries</span></a> for details and limitations.</p>\n</section>\n<section id=\"validation-of-constraints\">\n<h3>Validation of Constraints<a class=\"heading-anchor\" href=\"#validation-of-constraints\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><a class=\"reference internal\" href=\"/en/dev/ref/models/constraints/#django.db.models.CheckConstraint\" title=\"django.db.models.CheckConstraint\"><code class=\"xref py py-class docutils literal notranslate\">Check</code></a>,\n<a class=\"reference internal\" href=\"/en/dev/ref/models/constraints/#django.db.models.UniqueConstraint\" title=\"django.db.models.UniqueConstraint\"><code class=\"xref py py-class docutils literal notranslate\">unique</code></a>, and <a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/constraints/#django.contrib.postgres.constraints.ExclusionConstraint\" title=\"django.contrib.postgres.constraints.ExclusionConstraint\"><code class=\"xref py py-class docutils literal notranslate\">exclusion</code></a> constraints defined\nin the <a class=\"reference internal\" href=\"/en/dev/ref/models/options/#django.db.models.Options.constraints\" title=\"django.db.models.Options.constraints\"><code class=\"xref py py-attr docutils literal notranslate\">Meta.constraints</code></a> option\nare now checked during <a class=\"reference internal\" href=\"/en/dev/ref/models/instances/#validating-objects\"><span class=\"std std-ref\">model validation</span></a>.</p>\n</section>\n<section id=\"form-rendering-accessibility\">\n<h3>Form rendering accessibility<a class=\"heading-anchor\" href=\"#form-rendering-accessibility\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>In order to aid users with screen readers, and other assistive technology, new\n<code class=\"docutils literal notranslate\">&lt;div&gt;</code> based form templates are available from this release. These provide\nmore accessible navigation than the older templates, and are able to correctly\ngroup related controls, such as radio-lists, into fieldsets.</p>\n<p>The new templates are recommended, and will become the default form rendering\nstyle when outputting a form, like <code class=\"docutils literal notranslate\">{{ form }}</code> in a template, from Django\n5.0.</p>\n<p>In order to ease adopting the new output style, the default form and formset\ntemplates are now configurable at the project level via the\n<a class=\"reference internal\" href=\"/en/dev/ref/settings/#std-setting-FORM_RENDERER\"><code class=\"xref std std-setting docutils literal notranslate\">FORM_RENDERER</code></a> setting.</p>\n<p>See <a class=\"reference internal\" href=\"#forms-4-1\"><span class=\"std std-ref\">the Forms section (below)</span></a> for full details.</p>\n</section>\n<section id=\"csrf-cookie-masked-setting\">\n<span id=\"csrf-cookie-masked-usage\"></span><h3><code class=\"docutils literal notranslate\">CSRF_COOKIE_MASKED</code> setting<a class=\"heading-anchor\" href=\"#csrf-cookie-masked-setting\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The new <code class=\"docutils literal notranslate\">CSRF_COOKIE_MASKED</code> transitional setting allows specifying whether\nto mask the CSRF cookie.</p>\n<p><a class=\"reference internal\" href=\"/en/dev/ref/middleware/#django.middleware.csrf.CsrfViewMiddleware\" title=\"django.middleware.csrf.CsrfViewMiddleware\"><code class=\"xref py py-class docutils literal notranslate\">CsrfViewMiddleware</code></a> no longer masks the CSRF\ncookie like it does the CSRF token in the DOM. If you are upgrading multiple\ninstances of the same project to Django 4.1, you should set\n<code class=\"docutils literal notranslate\">CSRF_COOKIE_MASKED</code> to <code class=\"docutils literal notranslate\">True</code> during the transition, in order to allow\ncompatibility with the older versions of Django. Once the transition to 4.1 is\ncomplete you can stop overriding <code class=\"docutils literal notranslate\">CSRF_COOKIE_MASKED</code>.</p>\n<p>This setting is deprecated as of this release and will be removed in Django\n5.0.</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>The admin <a class=\"reference internal\" href=\"/en/dev/ref/contrib/admin/#admin-theming\"><span class=\"std std-ref\">dark mode CSS variables</span></a> are now applied in a\nseparate stylesheet and template block.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/contrib/admin/filters/#modeladmin-list-filters\"><span class=\"std std-ref\">ModelAdmin List Filters</span></a> providing custom <code class=\"docutils literal notranslate\">FieldListFilter</code>\nsubclasses can now control the query string value separator when filtering\nfor multiple values using the <code class=\"docutils literal notranslate\">__in</code> lookup.</p></li>\n<li><p>The admin <a class=\"reference internal\" href=\"/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.history_view\" title=\"django.contrib.admin.ModelAdmin.history_view\"><code class=\"xref py py-meth docutils literal notranslate\">history view</code></a>\nis now paginated.</p></li>\n<li><p>Related widget wrappers now have a link to object’s change form.</p></li>\n<li><p>The <a class=\"reference internal\" href=\"/en/dev/ref/contrib/admin/#django.contrib.admin.AdminSite.get_app_list\" title=\"django.contrib.admin.AdminSite.get_app_list\"><code class=\"xref py py-meth docutils literal notranslate\">AdminSite.get_app_list()</code></a> method now allows changing the order of\napps and models on the admin index page.</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\n320,000 to 390,000.</p></li>\n<li><p>The <a class=\"reference internal\" href=\"/en/dev/ref/contrib/auth/#django.contrib.auth.backends.RemoteUserBackend.configure_user\" title=\"django.contrib.auth.backends.RemoteUserBackend.configure_user\"><code class=\"xref py py-meth docutils literal notranslate\">RemoteUserBackend.configure_user()</code></a> method now allows synchronizing\nuser attributes with attributes in a remote system such as an LDAP directory.</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>The new <a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/geos/#django.contrib.gis.geos.GEOSGeometry.make_valid\" title=\"django.contrib.gis.geos.GEOSGeometry.make_valid\"><code class=\"xref py py-meth docutils literal notranslate\">GEOSGeometry.make_valid()</code></a> method allows converting invalid\ngeometries to valid ones.</p></li>\n<li><p>The new <code class=\"docutils literal notranslate\">clone</code> argument for <a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/geos/#django.contrib.gis.geos.GEOSGeometry.normalize\" title=\"django.contrib.gis.geos.GEOSGeometry.normalize\"><code class=\"xref py py-meth docutils literal notranslate\">GEOSGeometry.normalize()</code></a> allows\ncreating a normalized clone of the geometry.</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>The new <a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/aggregates/#django.contrib.postgres.aggregates.BitXor\" title=\"django.contrib.postgres.aggregates.BitXor\"><code class=\"xref py py-class docutils literal notranslate\">BitXor()</code></a>\naggregate function returns an <code class=\"docutils literal notranslate\">int</code> of the bitwise <code class=\"docutils literal notranslate\">XOR</code> of all non-null\ninput values.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/indexes/#django.contrib.postgres.indexes.SpGistIndex\" title=\"django.contrib.postgres.indexes.SpGistIndex\"><code class=\"xref py py-class docutils literal notranslate\">SpGistIndex</code></a> now supports covering\nindexes on PostgreSQL 14+.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/constraints/#django.contrib.postgres.constraints.ExclusionConstraint\" title=\"django.contrib.postgres.constraints.ExclusionConstraint\"><code class=\"xref py py-class docutils literal notranslate\">ExclusionConstraint</code></a> now\nsupports covering exclusion constraints using SP-GiST indexes on PostgreSQL\n14+.</p></li>\n<li><p>The new <code class=\"docutils literal notranslate\">default_bounds</code> attribute of <a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/fields/#django.contrib.postgres.fields.DateTimeRangeField.default_bounds\" title=\"django.contrib.postgres.fields.DateTimeRangeField.default_bounds\"><code class=\"xref py py-attr docutils literal notranslate\">DateTimeRangeField</code></a> and\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/fields/#django.contrib.postgres.fields.DecimalRangeField.default_bounds\" title=\"django.contrib.postgres.fields.DecimalRangeField.default_bounds\"><code class=\"xref py py-attr docutils literal notranslate\">DecimalRangeField</code></a> allows\nspecifying bounds for list and tuple inputs.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/constraints/#django.contrib.postgres.constraints.ExclusionConstraint\" title=\"django.contrib.postgres.constraints.ExclusionConstraint\"><code class=\"xref py py-class docutils literal notranslate\">ExclusionConstraint</code></a> now allows\nspecifying operator classes with the\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/indexes/#django.contrib.postgres.indexes.OpClass\" title=\"django.contrib.postgres.indexes.OpClass\"><code class=\"xref py py-class docutils literal notranslate\">OpClass()</code></a> expression.</p></li>\n</ul>\n</section>\n<section id=\"django-contrib-sitemaps\">\n<h4><a class=\"reference internal\" href=\"/en/dev/ref/contrib/sitemaps/#module-django.contrib.sitemaps\" title=\"django.contrib.sitemaps: A framework for generating Google sitemap XML files.\"><code class=\"xref py py-mod docutils literal notranslate\">django.contrib.sitemaps</code></a><a class=\"heading-anchor\" href=\"#django-contrib-sitemaps\"><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 sitemap index template <code class=\"docutils literal notranslate\">&lt;sitemapindex&gt;</code> now includes the\n<code class=\"docutils literal notranslate\">&lt;lastmod&gt;</code> timestamp where available, through the new\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/sitemaps/#django.contrib.sitemaps.Sitemap.get_latest_lastmod\" title=\"django.contrib.sitemaps.Sitemap.get_latest_lastmod\"><code class=\"xref py py-meth docutils literal notranslate\">get_latest_lastmod()</code></a> method. Custom\nsitemap index templates should be updated for the adjusted <a class=\"reference internal\" href=\"/en/dev/ref/contrib/sitemaps/#sitemap-index-context-variables\"><span class=\"std std-ref\">context\nvariables</span></a>.</p></li>\n</ul>\n</section>\n<section id=\"django-contrib-staticfiles\">\n<h4><a class=\"reference internal\" href=\"/en/dev/ref/contrib/staticfiles/#module-django.contrib.staticfiles\" title=\"django.contrib.staticfiles: An app for handling static files.\"><code class=\"xref py py-mod docutils literal notranslate\">django.contrib.staticfiles</code></a><a class=\"heading-anchor\" href=\"#django-contrib-staticfiles\"><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/staticfiles/#django.contrib.staticfiles.storage.ManifestStaticFilesStorage\" title=\"django.contrib.staticfiles.storage.ManifestStaticFilesStorage\"><code class=\"xref py py-class docutils literal notranslate\">ManifestStaticFilesStorage</code></a> now\nreplaces paths to CSS source map references with their hashed counterparts.</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>Third-party database backends can now specify the minimum required version of\nthe database using the <code class=\"docutils literal notranslate\">DatabaseFeatures.minimum_database_version</code>\nattribute which is a tuple (e.g. <code class=\"docutils literal notranslate\">(10, 0)</code> means “10.0”). If a minimum\nversion is specified, backends must also implement\n<code class=\"docutils literal notranslate\">DatabaseWrapper.get_database_version()</code>, which returns a tuple of the\ncurrent database version. The backend’s\n<code class=\"docutils literal notranslate\">DatabaseWrapper.init_connection_state()</code> method must call <code class=\"docutils literal notranslate\">super()</code> in\norder for the check to run.</p></li>\n</ul>\n</section>\n<section id=\"forms\">\n<span id=\"forms-4-1\"></span><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>\n<li><p>The default template used to render forms when cast to a string, e.g. in\ntemplates as <code class=\"docutils literal notranslate\">{{ form }}</code>, is now configurable at the project-level by\nsetting <a class=\"reference internal\" href=\"/en/dev/ref/forms/renderers/#django.forms.renderers.BaseRenderer.form_template_name\" title=\"django.forms.renderers.BaseRenderer.form_template_name\"><code class=\"xref py py-attr docutils literal notranslate\">form_template_name</code></a> on\nthe class provided for <a class=\"reference internal\" href=\"/en/dev/ref/settings/#std-setting-FORM_RENDERER\"><code class=\"xref std std-setting docutils literal notranslate\">FORM_RENDERER</code></a>.</p>\n<p><a class=\"reference internal\" href=\"/en/dev/ref/forms/api/#django.forms.Form.template_name\" title=\"django.forms.Form.template_name\"><code class=\"xref py py-attr docutils literal notranslate\">Form.template_name</code></a> is now a property deferring to the renderer, but\nmay be overridden with a string value to specify the template name per-form\nclass.</p>\n<p>Similarly, the default template used to render formsets can be specified via\nthe matching\n<a class=\"reference internal\" href=\"/en/dev/ref/forms/renderers/#django.forms.renderers.BaseRenderer.formset_template_name\" title=\"django.forms.renderers.BaseRenderer.formset_template_name\"><code class=\"xref py py-attr docutils literal notranslate\">formset_template_name</code></a> renderer\nattribute.</p>\n</li>\n<li><p>The new <code class=\"docutils literal notranslate\">div.html</code> form template, referencing\n<a class=\"reference internal\" href=\"/en/dev/ref/forms/api/#django.forms.Form.template_name_div\" title=\"django.forms.Form.template_name_div\"><code class=\"xref py py-attr docutils literal notranslate\">Form.template_name_div</code></a> attribute, and matching <a class=\"reference internal\" href=\"/en/dev/ref/forms/api/#django.forms.Form.as_div\" title=\"django.forms.Form.as_div\"><code class=\"xref py py-meth docutils literal notranslate\">Form.as_div()</code></a>\nmethod, render forms using HTML <code class=\"docutils literal notranslate\">&lt;div&gt;</code> elements.</p>\n<p>This new output style is recommended over the existing\n<a class=\"reference internal\" href=\"/en/dev/ref/forms/api/#django.forms.Form.as_table\" title=\"django.forms.Form.as_table\"><code class=\"xref py py-meth docutils literal notranslate\">as_table()</code></a>, <a class=\"reference internal\" href=\"/en/dev/ref/forms/api/#django.forms.Form.as_p\" title=\"django.forms.Form.as_p\"><code class=\"xref py py-meth docutils literal notranslate\">as_p()</code></a> and <a class=\"reference internal\" href=\"/en/dev/ref/forms/api/#django.forms.Form.as_ul\" title=\"django.forms.Form.as_ul\"><code class=\"xref py py-meth docutils literal notranslate\">as_ul()</code></a> styles,\nas the template implements <code class=\"docutils literal notranslate\">&lt;fieldset&gt;</code> and <code class=\"docutils literal notranslate\">&lt;legend&gt;</code> to group related\ninputs and is easier for screen reader users to navigate.</p>\n<p>The div-based output will become the default rendering style from Django 5.0.</p>\n</li>\n<li><p>In order to smooth adoption of the new <code class=\"docutils literal notranslate\">&lt;div&gt;</code> output style, two\ntransitional form renderer classes are available:\n<code class=\"docutils literal notranslate\">django.forms.renderers.DjangoDivFormRenderer</code> and\n<code class=\"docutils literal notranslate\">django.forms.renderers.Jinja2DivFormRenderer</code>, for the Django and Jinja2\ntemplate backends respectively.</p>\n<p>You can apply one of these via the <a class=\"reference internal\" href=\"/en/dev/ref/settings/#std-setting-FORM_RENDERER\"><code class=\"xref std std-setting docutils literal notranslate\">FORM_RENDERER</code></a> setting. For\nexample:</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>FORM_RENDERER <span class=\"o\">=</span> <span class=\"s2\">&quot;django.forms.renderers.DjangoDivFormRenderer&quot;</span>\n</code></pre></div>\n<p>Once the <code class=\"docutils literal notranslate\">&lt;div&gt;</code> output style is the default, from Django 5.0, these\ntransitional renderers will be deprecated, for removal in Django 6.0. The\n<code class=\"docutils literal notranslate\">FORM_RENDERER</code> declaration can be removed at that time.</p>\n</li>\n<li><p>If the new <code class=\"docutils literal notranslate\">&lt;div&gt;</code> output style is not appropriate for your project, you\nshould define a renderer subclass specifying\n<a class=\"reference internal\" href=\"/en/dev/ref/forms/renderers/#django.forms.renderers.BaseRenderer.form_template_name\" title=\"django.forms.renderers.BaseRenderer.form_template_name\"><code class=\"xref py py-attr docutils literal notranslate\">form_template_name</code></a> and\n<a class=\"reference internal\" href=\"/en/dev/ref/forms/renderers/#django.forms.renderers.BaseRenderer.formset_template_name\" title=\"django.forms.renderers.BaseRenderer.formset_template_name\"><code class=\"xref py py-attr docutils literal notranslate\">formset_template_name</code></a> for your\nrequired style, and set <a class=\"reference internal\" href=\"/en/dev/ref/settings/#std-setting-FORM_RENDERER\"><code class=\"xref std std-setting docutils literal notranslate\">FORM_RENDERER</code></a> accordingly.</p>\n<p>For example, for the <code class=\"docutils literal notranslate\">&lt;p&gt;</code> output style used by <a class=\"reference internal\" href=\"/en/dev/ref/forms/api/#django.forms.Form.as_p\" title=\"django.forms.Form.as_p\"><code class=\"xref py py-meth docutils literal notranslate\">as_p()</code></a>, you\nwould define a form renderer setting <code class=\"docutils literal notranslate\">form_template_name</code> to\n<code class=\"docutils literal notranslate\">&quot;django/forms/p.html&quot;</code> and <code class=\"docutils literal notranslate\">formset_template_name</code> to\n<code class=\"docutils literal notranslate\">&quot;django/forms/formsets/p.html&quot;</code>.</p>\n</li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/ref/forms/api/#django.forms.BoundField.legend_tag\" title=\"django.forms.BoundField.legend_tag\"><code class=\"xref py py-meth docutils literal notranslate\">legend_tag()</code></a> allows rendering field\nlabels in <code class=\"docutils literal notranslate\">&lt;legend&gt;</code> tags via the new <code class=\"docutils literal notranslate\">tag</code> argument of\n<a class=\"reference internal\" href=\"/en/dev/ref/forms/api/#django.forms.BoundField.label_tag\" title=\"django.forms.BoundField.label_tag\"><code class=\"xref py py-meth docutils literal notranslate\">label_tag()</code></a>.</p></li>\n<li><p>The new <code class=\"docutils literal notranslate\">edit_only</code> argument for <a class=\"reference internal\" href=\"/en/dev/ref/forms/models/#django.forms.models.modelformset_factory\" title=\"django.forms.models.modelformset_factory\"><code class=\"xref py py-func docutils literal notranslate\">modelformset_factory()</code></a> and\n<a class=\"reference internal\" href=\"/en/dev/ref/forms/models/#django.forms.models.inlineformset_factory\" title=\"django.forms.models.inlineformset_factory\"><code class=\"xref py py-func docutils literal notranslate\">inlineformset_factory()</code></a> allows preventing new objects creation.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">js</code> and <code class=\"docutils literal notranslate\">css</code> class attributes of <a class=\"reference internal\" href=\"/en/dev/topics/forms/media/\"><span class=\"doc\">Media</span></a>\nnow allow using hashable objects, not only path strings, as long as those\nobjects implement the <code class=\"docutils literal notranslate\">__html__()</code> method (typically when decorated with\nthe <a class=\"reference internal\" href=\"/en/dev/ref/utils/#django.utils.html.html_safe\" title=\"django.utils.html.html_safe\"><code class=\"xref py py-func docutils literal notranslate\">html_safe()</code></a> decorator).</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/ref/forms/api/#django.forms.BoundField.use_fieldset\" title=\"django.forms.BoundField.use_fieldset\"><code class=\"xref py py-attr docutils literal notranslate\">BoundField.use_fieldset</code></a> and <a class=\"reference internal\" href=\"/en/dev/ref/forms/widgets/#django.forms.Widget.use_fieldset\" title=\"django.forms.Widget.use_fieldset\"><code class=\"xref py py-attr docutils literal notranslate\">Widget.use_fieldset</code></a>\nattributes help to identify widgets where its inputs should be grouped in a\n<code class=\"docutils literal notranslate\">&lt;fieldset&gt;</code> with a <code class=\"docutils literal notranslate\">&lt;legend&gt;</code>.</p></li>\n<li><p>The <a class=\"reference internal\" href=\"/en/dev/topics/forms/formsets/#formsets-error-messages\"><span class=\"std std-ref\">error_messages</span></a> argument for\n<a class=\"reference internal\" href=\"/en/dev/topics/forms/formsets/#django.forms.formsets.BaseFormSet\" title=\"django.forms.formsets.BaseFormSet\"><code class=\"xref py py-class docutils literal notranslate\">BaseFormSet</code></a> now allows customizing\nerror messages for invalid number of forms by passing <code class=\"docutils literal notranslate\">'too_few_forms'</code>\nand <code class=\"docutils literal notranslate\">'too_many_forms'</code> keys.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/forms/fields/#django.forms.IntegerField\" title=\"django.forms.IntegerField\"><code class=\"xref py py-class docutils literal notranslate\">IntegerField</code></a>, <a class=\"reference internal\" href=\"/en/dev/ref/forms/fields/#django.forms.FloatField\" title=\"django.forms.FloatField\"><code class=\"xref py py-class docutils literal notranslate\">FloatField</code></a>, and\n<a class=\"reference internal\" href=\"/en/dev/ref/forms/fields/#django.forms.DecimalField\" title=\"django.forms.DecimalField\"><code class=\"xref py py-class docutils literal notranslate\">DecimalField</code></a> now optionally accept a <code class=\"docutils literal notranslate\">step_size</code>\nargument. This is used to set the <code class=\"docutils literal notranslate\">step</code> HTML attribute, and is validated\non form submission.</p></li>\n</ul>\n</section>\n<section id=\"internationalization\">\n<h4>Internationalization<a class=\"heading-anchor\" href=\"#internationalization\"><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/topics/i18n/translation/#django.conf.urls.i18n.i18n_patterns\" title=\"django.conf.urls.i18n.i18n_patterns\"><code class=\"xref py py-func docutils literal notranslate\">i18n_patterns()</code></a> function now supports\nlanguages with both scripts and regions.</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><a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#cmdoption-makemigrations-noinput\"><code class=\"xref std std-option docutils literal notranslate\">makemigrations --no-input</code></a> now logs default answers and reasons why\nmigrations cannot be created.</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#cmdoption-makemigrations-scriptable\"><code class=\"xref std std-option docutils literal notranslate\">makemigrations --scriptable</code></a> option diverts log output and\ninput prompts to <code class=\"docutils literal notranslate\">stderr</code>, writing only paths of generated migration files\nto <code class=\"docutils literal notranslate\">stdout</code>.</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#cmdoption-migrate-prune\"><code class=\"xref std std-option docutils literal notranslate\">migrate --prune</code></a> option allows deleting nonexistent\nmigrations from the <code class=\"docutils literal notranslate\">django_migrations</code> table.</p></li>\n<li><p>Python files created by <a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#django-admin-startproject\"><code class=\"xref std std-djadmin docutils literal notranslate\">startproject</code></a>, <a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#django-admin-startapp\"><code class=\"xref std std-djadmin docutils literal notranslate\">startapp</code></a>,\n<a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#django-admin-optimizemigration\"><code class=\"xref std std-djadmin docutils literal notranslate\">optimizemigration</code></a>, <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>, and\n<a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#django-admin-squashmigrations\"><code class=\"xref std std-djadmin docutils literal notranslate\">squashmigrations</code></a> are now formatted using the <code class=\"docutils literal notranslate\">black</code> command if\nit is present on your <code class=\"docutils literal notranslate\">PATH</code>.</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#django-admin-optimizemigration\"><code class=\"xref std std-djadmin docutils literal notranslate\">optimizemigration</code></a> command allows optimizing operations for\na migration.</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 <a class=\"reference internal\" href=\"/en/dev/ref/migration-operations/#django.db.migrations.operations.RenameIndex\" title=\"django.db.migrations.operations.RenameIndex\"><code class=\"xref py py-class docutils literal notranslate\">RenameIndex</code></a> operation\nallows renaming indexes defined in the\n<a class=\"reference internal\" href=\"/en/dev/ref/models/options/#django.db.models.Options.indexes\" title=\"django.db.models.Options.indexes\"><code class=\"xref py py-attr docutils literal notranslate\">Meta.indexes</code></a> or\n<code class=\"docutils literal notranslate\">index_together</code> options.</p></li>\n<li><p>The migrations autodetector now generates\n<a class=\"reference internal\" href=\"/en/dev/ref/migration-operations/#django.db.migrations.operations.RenameIndex\" title=\"django.db.migrations.operations.RenameIndex\"><code class=\"xref py py-class docutils literal notranslate\">RenameIndex</code></a> operations instead of\n<code class=\"docutils literal notranslate\">RemoveIndex</code> and <code class=\"docutils literal notranslate\">AddIndex</code>, when renaming indexes defined in the\n<a class=\"reference internal\" href=\"/en/dev/ref/models/options/#django.db.models.Options.indexes\" title=\"django.db.models.Options.indexes\"><code class=\"xref py py-attr docutils literal notranslate\">Meta.indexes</code></a>.</p></li>\n<li><p>The migrations autodetector now generates\n<a class=\"reference internal\" href=\"/en/dev/ref/migration-operations/#django.db.migrations.operations.RenameIndex\" title=\"django.db.migrations.operations.RenameIndex\"><code class=\"xref py py-class docutils literal notranslate\">RenameIndex</code></a> operations instead of\n<code class=\"docutils literal notranslate\">AlterIndexTogether</code> and <code class=\"docutils literal notranslate\">AddIndex</code>, when moving indexes defined in the\n<code class=\"docutils literal notranslate\">Meta.index_together</code> to the\n<a class=\"reference internal\" href=\"/en/dev/ref/models/options/#django.db.models.Options.indexes\" title=\"django.db.models.Options.indexes\"><code class=\"xref py py-attr docutils literal notranslate\">Meta.indexes</code></a>.</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>The <code class=\"docutils literal notranslate\">order_by</code> argument of the\n<a class=\"reference internal\" href=\"/en/dev/ref/models/expressions/#django.db.models.expressions.Window\" title=\"django.db.models.expressions.Window\"><code class=\"xref py py-class docutils literal notranslate\">Window</code></a> expression now accepts string\nreferences to fields and transforms.</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/ref/settings/#std-setting-CONN_HEALTH_CHECKS\"><code class=\"xref std std-setting docutils literal notranslate\">CONN_HEALTH_CHECKS</code></a> setting allows enabling health checks\nfor <a class=\"reference internal\" href=\"/en/dev/ref/databases/#persistent-database-connections\"><span class=\"std std-ref\">persistent database connections</span></a>\nin order to reduce the number of failed requests, e.g. after database server\nrestart.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.bulk_create\" title=\"django.db.models.query.QuerySet.bulk_create\"><code class=\"xref py py-meth docutils literal notranslate\">QuerySet.bulk_create()</code></a> now supports updating fields when a row\ninsertion fails uniqueness constraints. This is supported on MariaDB, MySQL,\nPostgreSQL, and SQLite 3.24+.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.iterator\" title=\"django.db.models.query.QuerySet.iterator\"><code class=\"xref py py-meth docutils literal notranslate\">QuerySet.iterator()</code></a> now supports prefetching related objects as long\nas the <code class=\"docutils literal notranslate\">chunk_size</code> argument is provided. In older versions, no prefetching\nwas done.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/models/querysets/#django.db.models.Q\" title=\"django.db.models.Q\"><code class=\"xref py py-class docutils literal notranslate\">Q</code></a> objects and querysets can now be combined using\n<code class=\"docutils literal notranslate\">^</code> as the exclusive or (<code class=\"docutils literal notranslate\">XOR</code>) operator. <code class=\"docutils literal notranslate\">XOR</code> is natively supported\non MariaDB and MySQL. For databases that do not support <code class=\"docutils literal notranslate\">XOR</code>, the query\nwill be converted to an equivalent using <code class=\"docutils literal notranslate\">AND</code>, <code class=\"docutils literal notranslate\">OR</code>, and <code class=\"docutils literal notranslate\">NOT</code>.</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/howto/custom-model-fields/#custom-field-non-db-attrs\"><span class=\"std std-ref\">Field.non_db_attrs</span></a> attribute\nallows customizing attributes of fields that don’t affect a column\ndefinition.</p></li>\n<li><p>On PostgreSQL, <code class=\"docutils literal notranslate\">AutoField</code>, <code class=\"docutils literal notranslate\">BigAutoField</code>, and <code class=\"docutils literal notranslate\">SmallAutoField</code> are\nnow created as identity columns rather than serial columns with sequences.</p></li>\n</ul>\n</section>\n<section id=\"requests-and-responses\">\n<h4>Requests and Responses<a class=\"heading-anchor\" href=\"#requests-and-responses\"><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/request-response/#django.http.HttpResponse.set_cookie\" title=\"django.http.HttpResponse.set_cookie\"><code class=\"xref py py-meth docutils literal notranslate\">HttpResponse.set_cookie()</code></a> now supports <a class=\"reference external\" href=\"https://docs.python.org/3/library/datetime.html#datetime.timedelta\" title=\"(in Python v3.14)\"><code class=\"xref py py-class docutils literal notranslate\">timedelta</code></a>\nobjects for the <code class=\"docutils literal notranslate\">max_age</code> argument.</p></li>\n</ul>\n</section>\n<section id=\"security\">\n<h4>Security<a class=\"heading-anchor\" href=\"#security\"><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/settings/#std-setting-SECRET_KEY_FALLBACKS\"><code class=\"xref std std-setting docutils literal notranslate\">SECRET_KEY_FALLBACKS</code></a> setting allows providing a list of\nvalues for secret key rotation.</p></li>\n<li><p>The <a class=\"reference internal\" href=\"/en/dev/ref/settings/#std-setting-SECURE_PROXY_SSL_HEADER\"><code class=\"xref std std-setting docutils literal notranslate\">SECURE_PROXY_SSL_HEADER</code></a> setting now supports a comma-separated\nlist of protocols in the header value.</p></li>\n</ul>\n</section>\n<section id=\"signals\">\n<h4>Signals<a class=\"heading-anchor\" href=\"#signals\"><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/signals/#django.db.models.signals.pre_delete\" title=\"django.db.models.signals.pre_delete\"><code class=\"xref py py-data docutils literal notranslate\">pre_delete</code></a> and\n<a class=\"reference internal\" href=\"/en/dev/ref/signals/#django.db.models.signals.post_delete\" title=\"django.db.models.signals.post_delete\"><code class=\"xref py py-data docutils literal notranslate\">post_delete</code></a> signals now dispatch the\n<code class=\"docutils literal notranslate\">origin</code> of the deletion.</p></li>\n</ul>\n</section>\n<section id=\"templates\">\n<span id=\"templates-4-1\"></span><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>The HTML <code class=\"docutils literal notranslate\">&lt;script&gt;</code> element <code class=\"docutils literal notranslate\">id</code> attribute is no longer required when\nwrapping the <a class=\"reference internal\" href=\"/en/dev/ref/templates/builtins/#std-templatefilter-json_script\"><code class=\"xref std std-tfilter docutils literal notranslate\">json_script</code></a> template filter.</p></li>\n<li><p>The <a class=\"reference internal\" href=\"/en/dev/ref/templates/api/#django.template.loaders.cached.Loader\" title=\"django.template.loaders.cached.Loader\"><code class=\"xref py py-class docutils literal notranslate\">cached template loader</code></a>\nis now enabled in development, when <a class=\"reference internal\" href=\"/en/dev/ref/settings/#std-setting-DEBUG\"><code class=\"xref std std-setting docutils literal notranslate\">DEBUG</code></a> is <code class=\"docutils literal notranslate\">True</code>, and\n<a class=\"reference internal\" href=\"/en/dev/ref/settings/#std-setting-TEMPLATES-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\">OPTIONS['loaders']</code></a> isn’t specified. You may\nspecify <code class=\"docutils literal notranslate\">OPTIONS['loaders']</code> to override this, if necessary.</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 class=\"simple\">\n<li><p>The <a class=\"reference internal\" href=\"/en/dev/topics/testing/advanced/#django.test.runner.DiscoverRunner\" title=\"django.test.runner.DiscoverRunner\"><code class=\"xref py py-class docutils literal notranslate\">DiscoverRunner</code></a> now supports running tests in parallel on\nmacOS, Windows, and any other systems where the default\n<a class=\"reference external\" href=\"https://docs.python.org/3/library/multiprocessing.html#module-multiprocessing\" title=\"(in Python v3.14)\"><code class=\"xref py py-mod docutils literal notranslate\">multiprocessing</code></a> start method is <code class=\"docutils literal notranslate\">spawn</code>.</p></li>\n<li><p>A nested atomic block marked as durable in <a class=\"reference internal\" href=\"/en/dev/topics/testing/tools/#django.test.TestCase\" title=\"django.test.TestCase\"><code class=\"xref py py-class docutils literal notranslate\">django.test.TestCase</code></a> now\nraises a <code class=\"docutils literal notranslate\">RuntimeError</code>, the same as outside of tests.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/topics/testing/tools/#django.test.SimpleTestCase.assertFormError\" title=\"django.test.SimpleTestCase.assertFormError\"><code class=\"xref py py-meth docutils literal notranslate\">SimpleTestCase.assertFormError()</code></a> and\n<a class=\"reference internal\" href=\"/en/dev/topics/testing/tools/#django.test.SimpleTestCase.assertFormSetError\" title=\"django.test.SimpleTestCase.assertFormSetError\"><code class=\"xref py py-meth docutils literal notranslate\">assertFormsetError()</code></a>\nnow support passing a form/formset object directly.</p></li>\n</ul>\n</section>\n<section id=\"urls\">\n<h4>URLs<a class=\"heading-anchor\" href=\"#urls\"><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/urlresolvers/#django.urls.ResolverMatch.captured_kwargs\" title=\"django.urls.ResolverMatch.captured_kwargs\"><code class=\"xref py py-attr docutils literal notranslate\">ResolverMatch.captured_kwargs</code></a> attribute stores the captured\nkeyword arguments, as parsed from the URL.</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/ref/urlresolvers/#django.urls.ResolverMatch.extra_kwargs\" title=\"django.urls.ResolverMatch.extra_kwargs\"><code class=\"xref py py-attr docutils literal notranslate\">ResolverMatch.extra_kwargs</code></a> attribute stores the additional\nkeyword arguments passed to the view function.</p></li>\n</ul>\n</section>\n<section id=\"utilities\">\n<h4>Utilities<a class=\"heading-anchor\" href=\"#utilities\"><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\">SimpleLazyObject</code> now supports addition operations.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/utils/#django.utils.safestring.mark_safe\" title=\"django.utils.safestring.mark_safe\"><code class=\"xref py py-func docutils literal notranslate\">mark_safe()</code></a> now preserves lazy objects.</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.StepValueValidator\" title=\"django.core.validators.StepValueValidator\"><code class=\"xref py py-class docutils literal notranslate\">StepValueValidator</code></a> checks if a value\nis an integral multiple of a given step size. This new validator is used for\nthe new <code class=\"docutils literal notranslate\">step_size</code> argument added to form fields representing numeric\nvalues.</p></li>\n</ul>\n</section>\n</section>\n</section>\n<section id=\"backwards-incompatible-changes-in-4-1\">\n<span id=\"backwards-incompatible-4-1\"></span><h2>Backwards incompatible changes in 4.1<a class=\"heading-anchor\" href=\"#backwards-incompatible-changes-in-4-1\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"database-backend-api\">\n<h3>Database backend API<a class=\"heading-anchor\" href=\"#database-backend-api\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>This section describes changes that may be needed in third-party database\nbackends.</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\">BaseDatabaseFeatures.has_case_insensitive_like</code> is changed from <code class=\"docutils literal notranslate\">True</code>\nto <code class=\"docutils literal notranslate\">False</code> to reflect the behavior of most databases.</p></li>\n<li><p><code class=\"docutils literal notranslate\">DatabaseIntrospection.get_key_columns()</code> is removed. Use\n<code class=\"docutils literal notranslate\">DatabaseIntrospection.get_relations()</code> instead.</p></li>\n<li><p><code class=\"docutils literal notranslate\">DatabaseOperations.ignore_conflicts_suffix_sql()</code> method is replaced by\n<code class=\"docutils literal notranslate\">DatabaseOperations.on_conflict_suffix_sql()</code> that accepts the <code class=\"docutils literal notranslate\">fields</code>,\n<code class=\"docutils literal notranslate\">on_conflict</code>, <code class=\"docutils literal notranslate\">update_fields</code>, and <code class=\"docutils literal notranslate\">unique_fields</code> arguments.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">ignore_conflicts</code> argument of the\n<code class=\"docutils literal notranslate\">DatabaseOperations.insert_statement()</code> method is replaced by\n<code class=\"docutils literal notranslate\">on_conflict</code> that accepts <code class=\"docutils literal notranslate\">django.db.models.constants.OnConflict</code>.</p></li>\n<li><p><code class=\"docutils literal notranslate\">DatabaseOperations._convert_field_to_tz()</code> is replaced by\n<code class=\"docutils literal notranslate\">DatabaseOperations._convert_sql_to_tz()</code> that accepts the <code class=\"docutils literal notranslate\">sql</code>,\n<code class=\"docutils literal notranslate\">params</code>, and <code class=\"docutils literal notranslate\">tzname</code> arguments.</p></li>\n<li><p>Several date and time methods on <code class=\"docutils literal notranslate\">DatabaseOperations</code> now take <code class=\"docutils literal notranslate\">sql</code> and\n<code class=\"docutils literal notranslate\">params</code> arguments instead of <code class=\"docutils literal notranslate\">field_name</code> and return 2-tuple containing\nsome SQL and the parameters to be interpolated into that SQL. The changed\nmethods have these new signatures:</p>\n<ul>\n<li><p><code class=\"docutils literal notranslate\">DatabaseOperations.date_extract_sql(lookup_type, sql, params)</code></p></li>\n<li><p><code class=\"docutils literal notranslate\">DatabaseOperations.datetime_extract_sql(lookup_type, sql, params, tzname)</code></p></li>\n<li><p><code class=\"docutils literal notranslate\">DatabaseOperations.time_extract_sql(lookup_type, sql, params)</code></p></li>\n<li><p><code class=\"docutils literal notranslate\">DatabaseOperations.date_trunc_sql(lookup_type, sql, params, tzname=None)</code></p></li>\n<li><p><code class=\"docutils literal notranslate\">DatabaseOperations.datetime_trunc_sql(self, lookup_type, sql, params, tzname)</code></p></li>\n<li><p><code class=\"docutils literal notranslate\">DatabaseOperations.time_trunc_sql(lookup_type, sql, params, tzname=None)</code></p></li>\n<li><p><code class=\"docutils literal notranslate\">DatabaseOperations.datetime_cast_date_sql(sql, params, tzname)</code></p></li>\n<li><p><code class=\"docutils literal notranslate\">DatabaseOperations.datetime_cast_time_sql(sql, params, tzname)</code></p></li>\n</ul>\n</li>\n</ul>\n</section>\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 GDAL 2.1 is removed.</p></li>\n<li><p>Support for PostGIS 2.4 is removed.</p></li>\n</ul>\n</section>\n<section id=\"dropped-support-for-postgresql-10\">\n<h3>Dropped support for PostgreSQL 10<a class=\"heading-anchor\" href=\"#dropped-support-for-postgresql-10\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Upstream support for PostgreSQL 10 ends in November 2022. Django 4.1 supports\nPostgreSQL 11 and higher.</p>\n</section>\n<section id=\"dropped-support-for-mariadb-10-2\">\n<h3>Dropped support for MariaDB 10.2<a class=\"heading-anchor\" href=\"#dropped-support-for-mariadb-10-2\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Upstream support for MariaDB 10.2 ends in May 2022. Django 4.1 supports MariaDB\n10.3 and higher.</p>\n</section>\n<section id=\"admin-changelist-searches-spanning-multi-valued-relationships-changes\">\n<h3>Admin changelist searches spanning multi-valued relationships changes<a class=\"heading-anchor\" href=\"#admin-changelist-searches-spanning-multi-valued-relationships-changes\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Admin changelist searches using multiple search terms are now applied in a\nsingle call to <code class=\"docutils literal notranslate\">filter()</code>, rather than in sequential <code class=\"docutils literal notranslate\">filter()</code> calls.</p>\n<p>For multi-valued relationships, this means that rows from the related model\nmust match all terms rather than any term. For example, if <code class=\"docutils literal notranslate\">search_fields</code>\nis set to <code class=\"docutils literal notranslate\">['child__name', 'child__age']</code>, and a user searches for\n<code class=\"docutils literal notranslate\">'Jamal 17'</code>, parent rows will be returned only if there is a relationship to\nsome 17-year-old child named Jamal, rather than also returning parents who\nmerely have a younger or older child named Jamal in addition to some other\n17-year-old.</p>\n<p>See the <a class=\"reference internal\" href=\"/en/dev/topics/db/queries/#spanning-multi-valued-relationships\"><span class=\"std std-ref\">Spanning multi-valued relationships</span></a> topic for more discussion of\nthis difference. In Django 4.0 and earlier,\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_search_results\" title=\"django.contrib.admin.ModelAdmin.get_search_results\"><code class=\"xref py py-meth docutils literal notranslate\">get_search_results()</code></a> followed the\nsecond example query, but this undocumented behavior led to queries with\nexcessive joins.</p>\n</section>\n<section id=\"reverse-foreign-key-changes-for-unsaved-model-instances\">\n<h3>Reverse foreign key changes for unsaved model instances<a class=\"heading-anchor\" href=\"#reverse-foreign-key-changes-for-unsaved-model-instances\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>In order to unify the behavior with many-to-many relations for unsaved model\ninstances, a reverse foreign key now raises <code class=\"docutils literal notranslate\">ValueError</code> when calling\n<a class=\"reference internal\" href=\"/en/dev/ref/models/relations/#django.db.models.fields.related.RelatedManager\" title=\"django.db.models.fields.related.RelatedManager\"><code class=\"xref py py-class docutils literal notranslate\">related managers</code></a> for\nunsaved objects.</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>Related managers for <a class=\"reference internal\" href=\"/en/dev/ref/models/fields/#django.db.models.ForeignKey\" title=\"django.db.models.ForeignKey\"><code class=\"xref py py-class docutils literal notranslate\">ForeignKey</code></a>,\n<a class=\"reference internal\" href=\"/en/dev/ref/models/fields/#django.db.models.ManyToManyField\" title=\"django.db.models.ManyToManyField\"><code class=\"xref py py-class docutils literal notranslate\">ManyToManyField</code></a>, and\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/contenttypes/#django.contrib.contenttypes.fields.GenericRelation\" title=\"django.contrib.contenttypes.fields.GenericRelation\"><code class=\"xref py py-class docutils literal notranslate\">GenericRelation</code></a> are now cached\non the <a class=\"reference internal\" href=\"/en/dev/ref/models/instances/#django.db.models.Model\" title=\"django.db.models.Model\"><code class=\"xref py py-class docutils literal notranslate\">Model</code></a> instance to which they belong. <em>This\nchange was reverted in Django 4.1.2.</em></p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/topics/testing/advanced/#django.test.runner.DiscoverRunner\" title=\"django.test.runner.DiscoverRunner\"><code class=\"xref py py-class docutils literal notranslate\">DiscoverRunner</code></a> now returns a non-zero error code\nfor unexpected successes from tests marked with\n<a class=\"reference external\" href=\"https://docs.python.org/3/library/unittest.html#unittest.expectedFailure\" title=\"(in Python v3.14)\"><code class=\"xref py py-func docutils literal notranslate\">unittest.expectedFailure()</code></a>.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/middleware/#django.middleware.csrf.CsrfViewMiddleware\" title=\"django.middleware.csrf.CsrfViewMiddleware\"><code class=\"xref py py-class docutils literal notranslate\">CsrfViewMiddleware</code></a> no longer masks the CSRF\ncookie like it does the CSRF token in the DOM.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/middleware/#django.middleware.csrf.CsrfViewMiddleware\" title=\"django.middleware.csrf.CsrfViewMiddleware\"><code class=\"xref py py-class docutils literal notranslate\">CsrfViewMiddleware</code></a> now uses\n<code class=\"docutils literal notranslate\">request.META['CSRF_COOKIE']</code> for storing the unmasked CSRF secret rather\nthan a masked version. This is an undocumented, private API.</p></li>\n<li><p>The <a class=\"reference internal\" href=\"/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.actions\" title=\"django.contrib.admin.ModelAdmin.actions\"><code class=\"xref py py-attr docutils literal notranslate\">ModelAdmin.actions</code></a> and\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.inlines\" title=\"django.contrib.admin.ModelAdmin.inlines\"><code class=\"xref py py-attr docutils literal notranslate\">inlines</code></a> attributes now default to an\nempty tuple rather than an empty list to discourage unintended mutation.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">type=&quot;text/css&quot;</code> attribute is no longer included in <code class=\"docutils literal notranslate\">&lt;link&gt;</code> tags\nfor CSS <a class=\"reference internal\" href=\"/en/dev/topics/forms/media/\"><span class=\"doc\">form media</span></a>.</p></li>\n<li><p><code class=\"docutils literal notranslate\">formset:added</code> and <code class=\"docutils literal notranslate\">formset:removed</code> JavaScript events are now pure\nJavaScript events and don’t depend on jQuery. See\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/admin/javascript/#admin-javascript-inline-form-events\"><span class=\"std std-ref\">Inline form events</span></a> for more details on the change.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">exc_info</code> argument of the undocumented\n<code class=\"docutils literal notranslate\">django.utils.log.log_response()</code> function is replaced by <code class=\"docutils literal notranslate\">exception</code>.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">size</code> argument of the undocumented\n<code class=\"docutils literal notranslate\">django.views.static.was_modified_since()</code> function is removed.</p></li>\n<li><p>The admin log out UI now uses <code class=\"docutils literal notranslate\">POST</code> requests.</p></li>\n<li><p>The undocumented <code class=\"docutils literal notranslate\">InlineAdminFormSet.non_form_errors</code> property is replaced\nby the <code class=\"docutils literal notranslate\">non_form_errors()</code> method. This is consistent with <code class=\"docutils literal notranslate\">BaseFormSet</code>.</p></li>\n<li><p>As per <a class=\"reference internal\" href=\"#templates-4-1\"><span class=\"std std-ref\">above</span></a>, the cached template loader is now\nenabled in development. You may specify <code class=\"docutils literal notranslate\">OPTIONS['loaders']</code> to override\nthis, if necessary.</p></li>\n<li><p>The undocumented <code class=\"docutils literal notranslate\">django.contrib.auth.views.SuccessURLAllowedHostsMixin</code>\nmixin is replaced by <code class=\"docutils literal notranslate\">RedirectURLMixin</code>.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/models/constraints/#django.db.models.BaseConstraint\" title=\"django.db.models.BaseConstraint\"><code class=\"xref py py-class docutils literal notranslate\">BaseConstraint</code></a> subclasses must implement\n<a class=\"reference internal\" href=\"/en/dev/ref/models/constraints/#django.db.models.BaseConstraint.validate\" title=\"django.db.models.BaseConstraint.validate\"><code class=\"xref py py-meth docutils literal notranslate\">validate()</code></a> method to allow those\nconstraints to be used for validation.</p></li>\n<li><p>The undocumented <code class=\"docutils literal notranslate\">URLResolver._is_callback()</code>,\n<code class=\"docutils literal notranslate\">URLResolver._callback_strs</code>, and <code class=\"docutils literal notranslate\">URLPattern.lookup_str()</code> are\nmoved to <code class=\"docutils literal notranslate\">django.contrib.admindocs.utils</code>.</p></li>\n<li><p>The <a class=\"reference internal\" href=\"/en/dev/ref/models/instances/#django.db.models.Model.full_clean\" title=\"django.db.models.Model.full_clean\"><code class=\"xref py py-meth docutils literal notranslate\">Model.full_clean()</code></a> method now converts an <code class=\"docutils literal notranslate\">exclude</code> value to a\n<code class=\"docutils literal notranslate\">set</code>. It’s also preferable to pass an <code class=\"docutils literal notranslate\">exclude</code> value as a <code class=\"docutils literal notranslate\">set</code> to\nthe <a class=\"reference internal\" href=\"/en/dev/ref/models/instances/#django.db.models.Model.clean_fields\" title=\"django.db.models.Model.clean_fields\"><code class=\"xref py py-meth docutils literal notranslate\">Model.clean_fields()</code></a>, <a class=\"reference internal\" href=\"/en/dev/ref/models/instances/#django.db.models.Model.full_clean\" title=\"django.db.models.Model.full_clean\"><code class=\"xref py py-meth docutils literal notranslate\">Model.full_clean()</code></a>,\n<a class=\"reference internal\" href=\"/en/dev/ref/models/instances/#django.db.models.Model.validate_unique\" title=\"django.db.models.Model.validate_unique\"><code class=\"xref py py-meth docutils literal notranslate\">Model.validate_unique()</code></a>, and <a class=\"reference internal\" href=\"/en/dev/ref/models/instances/#django.db.models.Model.validate_constraints\" title=\"django.db.models.Model.validate_constraints\"><code class=\"xref py py-meth docutils literal notranslate\">Model.validate_constraints()</code></a>\nmethods.</p></li>\n<li><p>The minimum supported version of <code class=\"docutils literal notranslate\">asgiref</code> is increased from 3.4.1 to\n3.5.2.</p></li>\n<li><p>Combined expressions no longer use the error-prone behavior of guessing\n<code class=\"docutils literal notranslate\">output_field</code> when argument types match. As a consequence, resolving an\n<code class=\"docutils literal notranslate\">output_field</code> for database functions and combined expressions may now\ncrash with mixed types. You will need to explicitly set the <code class=\"docutils literal notranslate\">output_field</code>\nin such cases.</p></li>\n<li><p>The <a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#django-admin-makemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">makemessages</code></a> command no longer changes <code class=\"docutils literal notranslate\">.po</code> files when up\nto date. In older versions, <code class=\"docutils literal notranslate\">POT-Creation-Date</code> was always updated.</p></li>\n</ul>\n</section>\n</section>\n<section id=\"features-deprecated-in-4-1\">\n<span id=\"deprecated-features-4-1\"></span><h2>Features deprecated in 4.1<a class=\"heading-anchor\" href=\"#features-deprecated-in-4-1\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"log-out-via-get\">\n<h3>Log out via GET<a class=\"heading-anchor\" href=\"#log-out-via-get\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Logging out via <code class=\"docutils literal notranslate\">GET</code> requests to the <a class=\"reference internal\" href=\"/en/dev/topics/auth/default/#django.contrib.auth.views.LogoutView\" title=\"django.contrib.auth.views.LogoutView\"><code class=\"xref py py-class docutils literal notranslate\">built-in logout view</code></a> is deprecated. Use <code class=\"docutils literal notranslate\">POST</code> requests\ninstead.</p>\n<p>If you want to retain the user experience of an HTML link, you can use a form\nthat is styled to appear as a link:</p>\n<div class=\"code-block\" data-language=\"html\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Html</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=\"Html code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">form</span> <span class=\"na\">id</span><span class=\"o\">=</span><span class=\"s\">&quot;logout-form&quot;</span> <span class=\"na\">method</span><span class=\"o\">=</span><span class=\"s\">&quot;post&quot;</span> <span class=\"na\">action</span><span class=\"o\">=</span><span class=\"s\">&quot;{% url &#39;admin:logout&#39; %}&quot;</span><span class=\"p\">&gt;</span>\n  {% csrf_token %}\n  <span class=\"p\">&lt;</span><span class=\"nt\">button</span> <span class=\"na\">type</span><span class=\"o\">=</span><span class=\"s\">&quot;submit&quot;</span><span class=\"p\">&gt;</span>{% translate &quot;Log out&quot; %}<span class=\"p\">&lt;/</span><span class=\"nt\">button</span><span class=\"p\">&gt;</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">form</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<div class=\"code-block\" data-language=\"css\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Css</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=\"Css code\"><code><span class=\"p\">#</span><span class=\"nn\">logout-form</span> <span class=\"p\">{</span>\n  <span class=\"k\">display</span><span class=\"p\">:</span> <span class=\"kc\">inline</span><span class=\"p\">;</span>\n<span class=\"p\">}</span>\n<span class=\"p\">#</span><span class=\"nn\">logout-form</span> <span class=\"nt\">button</span> <span class=\"p\">{</span>\n  <span class=\"k\">background</span><span class=\"p\">:</span> <span class=\"kc\">none</span><span class=\"p\">;</span>\n  <span class=\"k\">border</span><span class=\"p\">:</span> <span class=\"kc\">none</span><span class=\"p\">;</span>\n  <span class=\"k\">cursor</span><span class=\"p\">:</span> <span class=\"kc\">pointer</span><span class=\"p\">;</span>\n  <span class=\"k\">padding</span><span class=\"p\">:</span> <span class=\"mi\">0</span><span class=\"p\">;</span>\n  <span class=\"k\">text-decoration</span><span class=\"p\">:</span> <span class=\"kc\">underline</span><span class=\"p\">;</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n</section>\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>\n<li><p>The context for sitemap index templates of a flat list of URLs is deprecated.\nCustom sitemap index templates should be updated for the adjusted\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/sitemaps/#sitemap-index-context-variables\"><span class=\"std std-ref\">context variables</span></a>, expecting a list\nof objects with <code class=\"docutils literal notranslate\">location</code> and optional <code class=\"docutils literal notranslate\">lastmod</code> attributes.</p></li>\n<li><p><code class=\"docutils literal notranslate\">CSRF_COOKIE_MASKED</code> transitional setting is deprecated.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">name</code> argument of <a class=\"reference internal\" href=\"/en/dev/ref/utils/#django.utils.functional.cached_property\" title=\"django.utils.functional.cached_property\"><code class=\"xref py py-func docutils literal notranslate\">django.utils.functional.cached_property()</code></a> is\ndeprecated as it’s unnecessary as of Python 3.6.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">opclasses</code> argument of\n<code class=\"docutils literal notranslate\">django.contrib.postgres.constraints.ExclusionConstraint</code> is deprecated in\nfavor of using <a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/indexes/#django.contrib.postgres.indexes.OpClass\" title=\"django.contrib.postgres.indexes.OpClass\"><code class=\"xref py py-class docutils literal notranslate\">OpClass()</code></a>\nin <a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/constraints/#django.contrib.postgres.constraints.ExclusionConstraint.expressions\" title=\"django.contrib.postgres.constraints.ExclusionConstraint.expressions\"><code class=\"xref py py-attr docutils literal notranslate\">ExclusionConstraint.expressions</code></a>. To use it, you need to add\n<code class=\"docutils literal notranslate\">'django.contrib.postgres'</code> in your <a class=\"reference internal\" href=\"/en/dev/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\">INSTALLED_APPS</code></a>.</p>\n<p>After making this change, <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> will generate a new\nmigration with two operations: <code class=\"docutils literal notranslate\">RemoveConstraint</code> and <code class=\"docutils literal notranslate\">AddConstraint</code>.\nSince this change has no effect on the database schema,\nthe <a class=\"reference internal\" href=\"/en/dev/ref/migration-operations/#django.db.migrations.operations.SeparateDatabaseAndState\" title=\"django.db.migrations.operations.SeparateDatabaseAndState\"><code class=\"xref py py-class docutils literal notranslate\">SeparateDatabaseAndState</code></a>\noperation can be used to only update the migration state without running any\nSQL. Move the generated operations into the <code class=\"docutils literal notranslate\">state_operations</code> argument of\n<a class=\"reference internal\" href=\"/en/dev/ref/migration-operations/#django.db.migrations.operations.SeparateDatabaseAndState\" title=\"django.db.migrations.operations.SeparateDatabaseAndState\"><code class=\"xref py py-class docutils literal notranslate\">SeparateDatabaseAndState</code></a>. For\nexample:</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><span class=\"k\">class</span> <span class=\"nc\">Migration</span><span class=\"p\">(</span>migrations<span class=\"o\">.</span>Migration<span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n\n    operations <span class=\"o\">=</span> <span class=\"p\">[</span>\n        migrations<span class=\"o\">.</span>SeparateDatabaseAndState<span class=\"p\">(</span>\n            database_operations<span class=\"o\">=</span><span class=\"p\">[],</span>\n            state_operations<span class=\"o\">=</span><span class=\"p\">[</span>\n                migrations<span class=\"o\">.</span>RemoveConstraint<span class=\"p\">(</span><span class=\"o\">...</span><span class=\"p\">),</span>\n                migrations<span class=\"o\">.</span>AddConstraint<span class=\"p\">(</span><span class=\"o\">...</span><span class=\"p\">),</span>\n            <span class=\"p\">],</span>\n        <span class=\"p\">),</span>\n    <span class=\"p\">]</span>\n</code></pre></div>\n</li>\n<li><p>The undocumented ability to pass <code class=\"docutils literal notranslate\">errors=None</code> to\n<a class=\"reference internal\" href=\"/en/dev/topics/testing/tools/#django.test.SimpleTestCase.assertFormError\" title=\"django.test.SimpleTestCase.assertFormError\"><code class=\"xref py py-meth docutils literal notranslate\">SimpleTestCase.assertFormError()</code></a> and\n<a class=\"reference internal\" href=\"/en/dev/topics/testing/tools/#django.test.SimpleTestCase.assertFormSetError\" title=\"django.test.SimpleTestCase.assertFormSetError\"><code class=\"xref py py-meth docutils literal notranslate\">assertFormsetError()</code></a>\nis deprecated. Use <code class=\"docutils literal notranslate\">errors=[]</code> instead.</p></li>\n<li><p><code class=\"docutils literal notranslate\">django.contrib.sessions.serializers.PickleSerializer</code> is deprecated due to\nthe risk of remote code execution.</p></li>\n<li><p>The usage of <code class=\"docutils literal notranslate\">QuerySet.iterator()</code> on a queryset that prefetches related\nobjects without providing the <code class=\"docutils literal notranslate\">chunk_size</code> argument is deprecated. In older\nversions, no prefetching was done. Providing a value for <code class=\"docutils literal notranslate\">chunk_size</code>\nsignifies that the additional query per chunk needed to prefetch is desired.</p></li>\n<li><p>Passing unsaved model instances to related filters is deprecated. In Django\n5.0, the exception will be raised.</p></li>\n<li><p><code class=\"docutils literal notranslate\">created=True</code> is added to the signature of\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/auth/#django.contrib.auth.backends.RemoteUserBackend.configure_user\" title=\"django.contrib.auth.backends.RemoteUserBackend.configure_user\"><code class=\"xref py py-meth docutils literal notranslate\">RemoteUserBackend.configure_user()</code></a>. Support  for <code class=\"docutils literal notranslate\">RemoteUserBackend</code>\nsubclasses that do not accept this argument is deprecated.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">django.utils.timezone.utc</code> alias to <a class=\"reference external\" href=\"https://docs.python.org/3/library/datetime.html#datetime.timezone.utc\" title=\"(in Python v3.14)\"><code class=\"xref py py-attr docutils literal notranslate\">datetime.timezone.utc</code></a> is\ndeprecated. Use <a class=\"reference external\" href=\"https://docs.python.org/3/library/datetime.html#datetime.timezone.utc\" title=\"(in Python v3.14)\"><code class=\"xref py py-attr docutils literal notranslate\">datetime.timezone.utc</code></a> directly.</p></li>\n<li><p>Passing a response object and a form/formset name to\n<code class=\"docutils literal notranslate\">SimpleTestCase.assertFormError()</code> and <code class=\"docutils literal notranslate\">assertFormsetError()</code> is\ndeprecated. Use:</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>assertFormError<span class=\"p\">(</span>response<span class=\"o\">.</span>context<span class=\"p\">[</span><span class=\"s2\">&quot;form_name&quot;</span><span class=\"p\">],</span> <span class=\"o\">...</span><span class=\"p\">)</span>\nassertFormsetError<span class=\"p\">(</span>response<span class=\"o\">.</span>context<span class=\"p\">[</span><span class=\"s2\">&quot;formset_name&quot;</span><span class=\"p\">],</span> <span class=\"o\">...</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>or pass the form/formset object directly instead.</p>\n</li>\n<li><p>The undocumented <code class=\"docutils literal notranslate\">django.contrib.gis.admin.OpenLayersWidget</code> is deprecated.</p></li>\n<li><p><code class=\"docutils literal notranslate\">django.contrib.auth.hashers.CryptPasswordHasher</code> is deprecated.</p></li>\n<li><p>The ability to pass <code class=\"docutils literal notranslate\">nulls_first=False</code> or <code class=\"docutils literal notranslate\">nulls_last=False</code> to\n<code class=\"docutils literal notranslate\">Expression.asc()</code> and <code class=\"docutils literal notranslate\">Expression.desc()</code> methods, and the <code class=\"docutils literal notranslate\">OrderBy</code>\nexpression is deprecated. Use <code class=\"docutils literal notranslate\">None</code> instead.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">&quot;django/forms/default.html&quot;</code> and\n<code class=\"docutils literal notranslate\">&quot;django/forms/formsets/default.html&quot;</code> templates which are a proxy to the\ntable-based templates are deprecated. Use the specific template instead.</p></li>\n<li><p>The undocumented <code class=\"docutils literal notranslate\">LogoutView.get_next_page()</code> method is renamed to\n<code class=\"docutils literal notranslate\">get_success_url()</code>.</p></li>\n</ul>\n</section>\n</section>\n<section id=\"features-removed-in-4-1\">\n<h2>Features removed in 4.1<a class=\"heading-anchor\" href=\"#features-removed-in-4-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 4.1.</p>\n<p>See <a class=\"reference internal\" href=\"/en/dev/releases/3.2/#deprecated-features-3-2\"><span class=\"std std-ref\">Features deprecated in 3.2</span></a> for details on these changes, including how\nto remove usage of these features.</p>\n<ul class=\"simple\">\n<li><p>Support for assigning objects which don’t support creating deep copies with\n<code class=\"docutils literal notranslate\">copy.deepcopy()</code> to class attributes in <code class=\"docutils literal notranslate\">TestCase.setUpTestData()</code> is\nremoved.</p></li>\n<li><p>Support for using a boolean value in\n<a class=\"reference internal\" href=\"/en/dev/howto/custom-management-commands/#django.core.management.BaseCommand.requires_system_checks\" title=\"django.core.management.BaseCommand.requires_system_checks\"><code class=\"xref py py-attr docutils literal notranslate\">BaseCommand.requires_system_checks</code></a> is removed.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">whitelist</code> argument and <code class=\"docutils literal notranslate\">domain_whitelist</code> attribute of\n<code class=\"docutils literal notranslate\">django.core.validators.EmailValidator</code> are removed.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">default_app_config</code> application configuration variable is removed.</p></li>\n<li><p><code class=\"docutils literal notranslate\">TransactionTestCase.assertQuerysetEqual()</code> no longer calls <code class=\"docutils literal notranslate\">repr()</code> on a\nqueryset when compared to string values.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">django.core.cache.backends.memcached.MemcachedCache</code> backend is\nremoved.</p></li>\n<li><p>Support for the pre-Django 3.2 format of messages used by\n<code class=\"docutils literal notranslate\">django.contrib.messages.storage.cookie.CookieStorage</code> is removed.</p></li>\n</ul>\n</section>","rootId":"django-4-1-release-notes","toc":[{"title":"Python compatibility","anchor":"python-compatibility","children":[]},{"title":"What’s new in Django 4.1","anchor":"what-s-new-in-django-4-1","children":[{"title":"Asynchronous handlers for class-based views","anchor":"asynchronous-handlers-for-class-based-views","children":[]},{"title":"Asynchronous ORM interface","anchor":"asynchronous-orm-interface","children":[]},{"title":"Validation of Constraints","anchor":"validation-of-constraints","children":[]},{"title":"Form rendering accessibility","anchor":"form-rendering-accessibility","children":[]},{"title":"CSRF_COOKIE_MASKED setting","anchor":"csrf-cookie-masked-setting","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.sitemaps","anchor":"django-contrib-sitemaps","children":[]},{"title":"django.contrib.staticfiles","anchor":"django-contrib-staticfiles","children":[]},{"title":"Database backends","anchor":"database-backends","children":[]},{"title":"Forms","anchor":"forms","children":[]},{"title":"Internationalization","anchor":"internationalization","children":[]},{"title":"Management Commands","anchor":"management-commands","children":[]},{"title":"Migrations","anchor":"migrations","children":[]},{"title":"Models","anchor":"models","children":[]},{"title":"Requests and Responses","anchor":"requests-and-responses","children":[]},{"title":"Security","anchor":"security","children":[]},{"title":"Signals","anchor":"signals","children":[]},{"title":"Templates","anchor":"templates","children":[]},{"title":"Tests","anchor":"tests","children":[]},{"title":"URLs","anchor":"urls","children":[]},{"title":"Utilities","anchor":"utilities","children":[]},{"title":"Validators","anchor":"validators","children":[]}]}]},{"title":"Backwards incompatible changes in 4.1","anchor":"backwards-incompatible-changes-in-4-1","children":[{"title":"Database backend API","anchor":"database-backend-api","children":[]},{"title":"django.contrib.gis","anchor":"id1","children":[]},{"title":"Dropped support for PostgreSQL 10","anchor":"dropped-support-for-postgresql-10","children":[]},{"title":"Dropped support for MariaDB 10.2","anchor":"dropped-support-for-mariadb-10-2","children":[]},{"title":"Admin changelist searches spanning multi-valued relationships changes","anchor":"admin-changelist-searches-spanning-multi-valued-relationships-changes","children":[]},{"title":"Reverse foreign key changes for unsaved model instances","anchor":"reverse-foreign-key-changes-for-unsaved-model-instances","children":[]},{"title":"Miscellaneous","anchor":"miscellaneous","children":[]}]},{"title":"Features deprecated in 4.1","anchor":"features-deprecated-in-4-1","children":[{"title":"Log out via GET","anchor":"log-out-via-get","children":[]},{"title":"Miscellaneous","anchor":"id2","children":[]}]},{"title":"Features removed in 4.1","anchor":"features-removed-in-4-1","children":[]}],"breadcrumbs":[{"docname":"releases/index","title":"Release notes","url":"/en/dev/releases/"}],"prev":{"docname":"releases/4.1.1","title":"Django 4.1.1 release notes","url":"/en/dev/releases/4.1.1/"},"next":{"docname":"releases/4.0.10","title":"Django 4.0.10 release notes","url":"/en/dev/releases/4.0.10/"},"formats":{"html":"/en/dev/releases/4.1/","markdown":"/en/dev/releases/4.1.md","json":"/en/dev/releases/4.1.json"},"source":"https://github.com/django/django/blob/main/docs/releases/4.1.txt","official":"https://docs.djangoproject.com/en/dev/releases/4.1/","inVersions":["dev","6.1","6.0","5.2","5.1","5.0","4.2","4.1"],"inLocales":["en"]}