{"title":"Django 4.2 release notes","version":"dev","locale":"en","docname":"releases/4.2","url":"/en/dev/releases/4.2/","canonical":"https://djangodocs.dev/en/dev/releases/4.2/","summary":"Welcome to Django 4.2! 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.2 release notes<a class=\"heading-anchor\" href=\"#django-4-2-release-notes\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p><em>April 3, 2023</em></p>\n<p>Welcome to Django 4.2!</p>\n<p>These release notes cover the <a class=\"reference internal\" href=\"#whats-new-4-2\"><span class=\"std std-ref\">new features</span></a>, as well as\nsome <a class=\"reference internal\" href=\"#backwards-incompatible-4-2\"><span class=\"std std-ref\">backwards incompatible changes</span></a> you’ll\nwant to be aware of when upgrading from Django 4.1 or earlier. We’ve\n<a class=\"reference internal\" href=\"#deprecated-features-4-2\"><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<p>Django 4.2 is designated as a <a class=\"reference internal\" href=\"/en/dev/internals/release-process/#term-Long-term-support-release\"><span class=\"xref std std-term\">long-term support release</span></a>. It will receive security updates for at least\nthree years after its release. Support for the previous LTS, Django 3.2, will\nend in April 2024.</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.2 supports Python 3.8, 3.9, 3.10, 3.11, and 3.12 (as of 4.2.8). 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-2\">\n<span id=\"whats-new-4-2\"></span><h2>What’s new in Django 4.2<a class=\"heading-anchor\" href=\"#what-s-new-in-django-4-2\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"psycopg-3-support\">\n<h3>Psycopg 3 support<a class=\"heading-anchor\" href=\"#psycopg-3-support\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django now supports <a class=\"reference external\" href=\"https://www.psycopg.org/psycopg3/\">psycopg</a> version 3.1.8 or higher. To update your code,\ninstall the <a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/psycopg/\">psycopg library</a>, you don’t need to change the\n<a class=\"reference internal\" href=\"/en/dev/ref/settings/#std-setting-DATABASE-ENGINE\"><code class=\"xref std std-setting docutils literal notranslate\">ENGINE</code></a> as <code class=\"docutils literal notranslate\">django.db.backends.postgresql</code>\nsupports both libraries.</p>\n<p>Support for <code class=\"docutils literal notranslate\">psycopg2</code> is likely to be deprecated and removed at some point\nin the future.</p>\n<p>Be aware that <code class=\"docutils literal notranslate\">psycopg</code> 3 introduces some breaking changes over <code class=\"docutils literal notranslate\">psycopg2</code>.\nAs a consequence, you may need to make some changes to account for\n<a class=\"reference external\" href=\"https://www.psycopg.org/psycopg3/docs/basic/from_pg2.html\">differences from psycopg2</a>.</p>\n</section>\n<section id=\"comments-on-columns-and-tables\">\n<h3>Comments on columns and tables<a class=\"heading-anchor\" href=\"#comments-on-columns-and-tables\"><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/models/fields/#django.db.models.Field.db_comment\" title=\"django.db.models.Field.db_comment\"><code class=\"xref py py-attr docutils literal notranslate\">Field.db_comment</code></a> and\n<a class=\"reference internal\" href=\"/en/dev/ref/models/options/#django.db.models.Options.db_table_comment\" title=\"django.db.models.Options.db_table_comment\"><code class=\"xref py py-attr docutils literal notranslate\">Meta.db_table_comment</code></a>\noptions allow creating comments on columns and tables, respectively. 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=\"kn\">from</span> <span class=\"nn\">django.db</span> <span class=\"kn\">import</span> models\n\n\n<span class=\"k\">class</span> <span class=\"nc\">Question</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    text <span class=\"o\">=</span> models<span class=\"o\">.</span>TextField<span class=\"p\">(</span>db_comment<span class=\"o\">=</span><span class=\"s2\">&quot;Poll question&quot;</span><span class=\"p\">)</span>\n    pub_date <span class=\"o\">=</span> models<span class=\"o\">.</span>DateTimeField<span class=\"p\">(</span>\n        db_comment<span class=\"o\">=</span><span class=\"s2\">&quot;Date and time when the question was published&quot;</span><span class=\"p\">,</span>\n    <span class=\"p\">)</span>\n\n    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        db_table_comment <span class=\"o\">=</span> <span class=\"s2\">&quot;Poll questions&quot;</span>\n\n\n<span class=\"k\">class</span> <span class=\"nc\">Answer</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    question <span class=\"o\">=</span> models<span class=\"o\">.</span>ForeignKey<span class=\"p\">(</span>\n        Question<span class=\"p\">,</span>\n        on_delete<span class=\"o\">=</span>models<span class=\"o\">.</span>CASCADE<span class=\"p\">,</span>\n        db_comment<span class=\"o\">=</span><span class=\"s2\">&quot;Reference to a question&quot;</span><span class=\"p\">,</span>\n    <span class=\"p\">)</span>\n    answer <span class=\"o\">=</span> models<span class=\"o\">.</span>TextField<span class=\"p\">(</span>db_comment<span class=\"o\">=</span><span class=\"s2\">&quot;Question answer&quot;</span><span class=\"p\">)</span>\n\n    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        db_table_comment <span class=\"o\">=</span> <span class=\"s2\">&quot;Question answers&quot;</span>\n</code></pre></div>\n<p>Also, the new <a class=\"reference internal\" href=\"/en/dev/ref/migration-operations/#django.db.migrations.operations.AlterModelTableComment\" title=\"django.db.migrations.operations.AlterModelTableComment\"><code class=\"xref py py-class docutils literal notranslate\">AlterModelTableComment</code></a>\noperation allows changing table comments defined in the\n<a class=\"reference internal\" href=\"/en/dev/ref/models/options/#django.db.models.Options.db_table_comment\" title=\"django.db.models.Options.db_table_comment\"><code class=\"xref py py-attr docutils literal notranslate\">Meta.db_table_comment</code></a>.</p>\n</section>\n<section id=\"mitigation-for-the-breach-attack\">\n<h3>Mitigation for the BREACH attack<a class=\"heading-anchor\" href=\"#mitigation-for-the-breach-attack\"><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/middleware/#django.middleware.gzip.GZipMiddleware\" title=\"django.middleware.gzip.GZipMiddleware\"><code class=\"xref py py-class docutils literal notranslate\">GZipMiddleware</code></a> now includes a mitigation for\nthe BREACH attack. It will add up to 100 random bytes to gzip responses to make\nBREACH attacks harder. Read more about the mitigation technique in the <a class=\"reference external\" href=\"https://ieeexplore.ieee.org/document/9754554\">Heal\nThe Breach (HTB) paper</a>.</p>\n</section>\n<section id=\"in-memory-file-storage\">\n<h3>In-memory file storage<a class=\"heading-anchor\" href=\"#in-memory-file-storage\"><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/files/storage/#django.core.files.storage.InMemoryStorage\" title=\"django.core.files.storage.InMemoryStorage\"><code class=\"xref py py-class docutils literal notranslate\">django.core.files.storage.InMemoryStorage</code></a> class provides a\nnon-persistent storage useful for speeding up tests by avoiding disk access.</p>\n</section>\n<section id=\"custom-file-storages\">\n<h3>Custom file storages<a class=\"heading-anchor\" href=\"#custom-file-storages\"><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/settings/#std-setting-STORAGES\"><code class=\"xref std std-setting docutils literal notranslate\">STORAGES</code></a> setting allows configuring multiple custom file\nstorage backends. It also controls storage engines for managing\n<a class=\"reference internal\" href=\"/en/dev/topics/files/\"><span class=\"doc\">files</span></a> (the <code class=\"docutils literal notranslate\">&quot;default&quot;</code> key) and <a class=\"reference internal\" href=\"/en/dev/ref/contrib/staticfiles/\"><span class=\"doc\">static files</span></a> (the <code class=\"docutils literal notranslate\">&quot;staticfiles&quot;</code> key).</p>\n<p>The old <code class=\"docutils literal notranslate\">DEFAULT_FILE_STORAGE</code> and <code class=\"docutils literal notranslate\">STATICFILES_STORAGE</code> settings are\ndeprecated as of this release.</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 light or dark color theme of the admin can now be toggled in the UI, as\nwell as being set to follow the system setting.</p></li>\n<li><p>The admin’s font stack now prefers system UI fonts and no longer requires\ndownloading fonts. Additionally, CSS variables are available to more easily\noverride the default font families.</p></li>\n<li><p>The <a class=\"extlink-source reference external\" href=\"https://github.com/django/django/blob/main/django/contrib/admin/templates/admin/delete_confirmation.html\">admin/delete_confirmation.html</a> template now\nhas some additional blocks and scripting hooks to ease customization.</p></li>\n<li><p>The chosen options of\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.filter_horizontal\" title=\"django.contrib.admin.ModelAdmin.filter_horizontal\"><code class=\"xref py py-attr docutils literal notranslate\">filter_horizontal</code></a> and\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.filter_vertical\" title=\"django.contrib.admin.ModelAdmin.filter_vertical\"><code class=\"xref py py-attr docutils literal notranslate\">filter_vertical</code></a> widgets are now\nfilterable.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">admin/base.html</code> template now has a new block <code class=\"docutils literal notranslate\">nav-breadcrumbs</code>\nwhich contains the navigation landmark and the <code class=\"docutils literal notranslate\">breadcrumbs</code> block.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_editable\" title=\"django.contrib.admin.ModelAdmin.list_editable\"><code class=\"xref py py-attr docutils literal notranslate\">ModelAdmin.list_editable</code></a> now uses atomic transactions when making\nedits.</p></li>\n<li><p>jQuery is upgraded from version 3.6.0 to 3.6.4.</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\n390,000 to 600,000.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/topics/auth/default/#django.contrib.auth.forms.UserCreationForm\" title=\"django.contrib.auth.forms.UserCreationForm\"><code class=\"xref py py-class docutils literal notranslate\">UserCreationForm</code></a> now saves many-to-many\nform fields for a custom user model.</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/topics/auth/default/#django.contrib.auth.forms.BaseUserCreationForm\" title=\"django.contrib.auth.forms.BaseUserCreationForm\"><code class=\"xref py py-class docutils literal notranslate\">BaseUserCreationForm</code></a> is now the\nrecommended base class for customizing the user creation form.</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 <a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/serializers/\"><span class=\"doc\">GeoJSON serializer</span></a> now outputs the\n<code class=\"docutils literal notranslate\">id</code> key for serialized features, which defaults to the primary key of\nobjects.</p></li>\n<li><p>The <a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/gdal/#django.contrib.gis.gdal.GDALRaster\" title=\"django.contrib.gis.gdal.GDALRaster\"><code class=\"xref py py-class docutils literal notranslate\">GDALRaster</code></a> class now supports\n<a class=\"reference external\" href=\"https://docs.python.org/3/library/pathlib.html#pathlib.Path\" title=\"(in Python v3.14)\"><code class=\"xref py py-class docutils literal notranslate\">pathlib.Path</code></a>.</p></li>\n<li><p>The <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> class now supports  <code class=\"docutils literal notranslate\">.mmdb</code>\nfiles downloaded from DB-IP.</p></li>\n<li><p>The OpenLayers template widget no longer includes inline CSS (which also\nremoves the former <code class=\"docutils literal notranslate\">map_css</code> block) to better comply with a strict Content\nSecurity Policy.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/forms-api/#django.contrib.gis.forms.widgets.OpenLayersWidget\" title=\"django.contrib.gis.forms.widgets.OpenLayersWidget\"><code class=\"xref py py-class docutils literal notranslate\">OpenLayersWidget</code></a> is now based on\nOpenLayers 7.2.2 (previously 4.6.5).</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/geoquerysets/#std-fieldlookup-isempty\"><code class=\"xref std std-lookup docutils literal notranslate\">isempty</code></a> lookup and\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/functions/#django.contrib.gis.db.models.functions.IsEmpty\" title=\"django.contrib.gis.db.models.functions.IsEmpty\"><code class=\"xref py py-class docutils literal notranslate\">IsEmpty()</code></a>\nexpression allow filtering empty geometries on PostGIS.</p></li>\n<li><p>The new <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>\nand <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>\nfunctions allow creating geometries from Well-known binary (WKB) and\nWell-known text (WKT) representations.</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/lookups/#std-fieldlookup-trigram_strict_word_similar\"><code class=\"xref std std-lookup docutils literal notranslate\">trigram_strict_word_similar</code></a> lookup, and the\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/search/#django.contrib.postgres.search.TrigramStrictWordSimilarity\" title=\"django.contrib.postgres.search.TrigramStrictWordSimilarity\"><code class=\"xref py py-class docutils literal notranslate\">TrigramStrictWordSimilarity()</code></a> and\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/search/#django.contrib.postgres.search.TrigramStrictWordDistance\" title=\"django.contrib.postgres.search.TrigramStrictWordDistance\"><code class=\"xref py py-class docutils literal notranslate\">TrigramStrictWordDistance()</code></a> expressions allow\nusing trigram strict word similarity.</p></li>\n<li><p>The <a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/fields/#std-fieldlookup-arrayfield.overlap\"><code class=\"xref std std-lookup docutils literal notranslate\">arrayfield.overlap</code></a> lookup now supports <code class=\"docutils literal notranslate\">QuerySet.values()</code>\nand <code class=\"docutils literal notranslate\">values_list()</code> as a right-hand side.</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 new <a class=\"reference internal\" href=\"/en/dev/ref/contrib/sitemaps/#django.contrib.sitemaps.Sitemap.get_languages_for_item\" title=\"django.contrib.sitemaps.Sitemap.get_languages_for_item\"><code class=\"xref py py-meth docutils literal notranslate\">Sitemap.get_languages_for_item()</code></a> method allows customizing the\nlist of languages for which the item is displayed.</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\nhas experimental support for replacing paths to JavaScript modules in\n<code class=\"docutils literal notranslate\">import</code> and <code class=\"docutils literal notranslate\">export</code> statements with their hashed counterparts. If you\nwant to try it, subclass <code class=\"docutils literal notranslate\">ManifestStaticFilesStorage</code> and set the\n<code class=\"docutils literal notranslate\">support_js_module_import_aggregation</code> attribute to <code class=\"docutils literal notranslate\">True</code>.</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/ref/contrib/staticfiles/#django.contrib.staticfiles.storage.ManifestStaticFilesStorage.manifest_hash\" title=\"django.contrib.staticfiles.storage.ManifestStaticFilesStorage.manifest_hash\"><code class=\"xref py py-attr docutils literal notranslate\">ManifestStaticFilesStorage.manifest_hash</code></a> attribute provides\na hash over all files in the manifest and changes whenever one of the files\nchanges.</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>The new <code class=\"docutils literal notranslate\">&quot;assume_role&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\nPostgreSQL to allow specifying the <a class=\"reference internal\" href=\"/en/dev/ref/databases/#database-role\"><span class=\"std std-ref\">session role</span></a>.</p></li>\n<li><p>The new <code class=\"docutils literal notranslate\">&quot;server_side_binding&quot;</code> option is now supported in\n<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 with <code class=\"docutils literal notranslate\">psycopg</code> 3.1.8+ to allow using\n<a class=\"reference internal\" href=\"/en/dev/ref/databases/#database-server-side-parameters-binding\"><span class=\"std std-ref\">server-side binding cursors</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>The debug page now shows <span class=\"target\" id=\"index-0\"></span><a class=\"pep reference external\" href=\"https://peps.python.org/pep-0678/\"><strong>exception notes</strong></a> and\n<span class=\"target\" id=\"index-1\"></span><a class=\"pep reference external\" href=\"https://peps.python.org/pep-0657/\"><strong>fine-grained error locations</strong></a> on Python 3.11+.</p></li>\n<li><p>Session cookies are now treated as credentials and therefore hidden and\nreplaced with stars (<code class=\"docutils literal notranslate\">**********</code>) in error reports.</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><a class=\"reference internal\" href=\"/en/dev/topics/forms/modelforms/#django.forms.ModelForm\" title=\"django.forms.ModelForm\"><code class=\"xref py py-class docutils literal notranslate\">ModelForm</code></a> now accepts the new <code class=\"docutils literal notranslate\">Meta</code> option\n<code class=\"docutils literal notranslate\">formfield_callback</code> to customize form fields.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/forms/models/#django.forms.models.modelform_factory\" title=\"django.forms.models.modelform_factory\"><code class=\"xref py py-func docutils literal notranslate\">modelform_factory()</code></a> now respects the\n<code class=\"docutils literal notranslate\">formfield_callback</code> attribute of the <code class=\"docutils literal notranslate\">form</code>’s <code class=\"docutils literal notranslate\">Meta</code>.</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>Added support and translations for the Central Kurdish (Sorani) language.</p></li>\n</ul>\n</section>\n<section id=\"logging\">\n<h4>Logging<a class=\"heading-anchor\" href=\"#logging\"><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/logging/#django-db-logger\"><span class=\"std std-ref\">django.db.backends</span></a> logger now logs transaction management queries\n(<code class=\"docutils literal notranslate\">BEGIN</code>, <code class=\"docutils literal notranslate\">COMMIT</code>, and <code class=\"docutils literal notranslate\">ROLLBACK</code>) at the <code class=\"docutils literal notranslate\">DEBUG</code> level.</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/#django-admin-makemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">makemessages</code></a> command now supports locales with private sub-tags\nsuch as <code class=\"docutils literal notranslate\">nl_NL-x-informal</code>.</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#cmdoption-makemigrations-update\"><code class=\"xref std std-option docutils literal notranslate\">makemigrations --update</code></a> option merges model changes into\nthe latest migration and optimizes the resulting operations.</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>Migrations now support serialization of <code class=\"docutils literal notranslate\">enum.Flag</code> objects.</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><code class=\"docutils literal notranslate\">QuerySet</code> now extensively supports filtering against\n<a class=\"reference internal\" href=\"/en/dev/ref/models/database-functions/#window-functions\"><span class=\"std std-ref\">UUID functions</span></a> with the exception of disjunctive filter lookups\nagainst window functions when performing aggregation.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.prefetch_related\" title=\"django.db.models.query.QuerySet.prefetch_related\"><code class=\"xref py py-meth docutils literal notranslate\">prefetch_related()</code></a> now supports\n<a class=\"reference internal\" href=\"/en/dev/ref/models/querysets/#django.db.models.Prefetch\" title=\"django.db.models.Prefetch\"><code class=\"xref py py-class docutils literal notranslate\">Prefetch</code></a> objects with sliced querysets.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/models/lookups/#lookup-registration-api\"><span class=\"std std-ref\">Registering lookups</span></a> on\n<a class=\"reference internal\" href=\"/en/dev/ref/models/fields/#django.db.models.Field\" title=\"django.db.models.Field\"><code class=\"xref py py-class docutils literal notranslate\">Field</code></a> instances is now supported.</p></li>\n<li><p>The new <code class=\"docutils literal notranslate\">robust</code> argument for <a class=\"reference internal\" href=\"/en/dev/topics/db/transactions/#django.db.transaction.on_commit\" title=\"django.db.transaction.on_commit\"><code class=\"xref py py-func docutils literal notranslate\">on_commit()</code></a>\nallows performing actions that can fail after a database transaction is\nsuccessfully committed.</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/topics/db/queries/#django.db.models.fields.json.KT\" title=\"django.db.models.fields.json.KT\"><code class=\"xref py py-class docutils literal notranslate\">KT()</code></a> expression represents\nthe text value of a key, index, or path transform of\n<a class=\"reference internal\" href=\"/en/dev/ref/models/fields/#django.db.models.JSONField\" title=\"django.db.models.JSONField\"><code class=\"xref py py-class docutils literal notranslate\">JSONField</code></a>.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/models/database-functions/#django.db.models.functions.Now\" title=\"django.db.models.functions.Now\"><code class=\"xref py py-class docutils literal notranslate\">Now</code></a> now supports microsecond precision\non MySQL and millisecond precision on SQLite.</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> expressions that output <code class=\"docutils literal notranslate\">BooleanField</code>\ncan now be negated using <code class=\"docutils literal notranslate\">~F()</code> (inversion operator).</p></li>\n<li><p><code class=\"docutils literal notranslate\">Model</code> now provides asynchronous versions of some methods that use the\ndatabase, using an <code class=\"docutils literal notranslate\">a</code> prefix: <a class=\"reference internal\" href=\"/en/dev/ref/models/instances/#django.db.models.Model.adelete\" title=\"django.db.models.Model.adelete\"><code class=\"xref py py-meth docutils literal notranslate\">adelete()</code></a>,\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\">arefresh_from_db()</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\">asave()</code></a>.</p></li>\n<li><p>Related managers now provide asynchronous versions of methods that change a\nset of related objects, using an <code class=\"docutils literal notranslate\">a</code> prefix: <a class=\"reference internal\" href=\"/en/dev/ref/models/relations/#django.db.models.fields.related.RelatedManager.aadd\" title=\"django.db.models.fields.related.RelatedManager.aadd\"><code class=\"xref py py-meth docutils literal notranslate\">aadd()</code></a>,\n<a class=\"reference internal\" href=\"/en/dev/ref/models/relations/#django.db.models.fields.related.RelatedManager.aclear\" title=\"django.db.models.fields.related.RelatedManager.aclear\"><code class=\"xref py py-meth docutils literal notranslate\">aclear()</code></a>, <a class=\"reference internal\" href=\"/en/dev/ref/models/relations/#django.db.models.fields.related.RelatedManager.aremove\" title=\"django.db.models.fields.related.RelatedManager.aremove\"><code class=\"xref py py-meth docutils literal notranslate\">aremove()</code></a>, and\n<a class=\"reference internal\" href=\"/en/dev/ref/models/relations/#django.db.models.fields.related.RelatedManager.aset\" title=\"django.db.models.fields.related.RelatedManager.aset\"><code class=\"xref py py-meth docutils literal notranslate\">aset()</code></a>.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/models/fields/#django.db.models.CharField.max_length\" title=\"django.db.models.CharField.max_length\"><code class=\"xref py py-attr docutils literal notranslate\">CharField.max_length</code></a> is no\nlonger required to be set on PostgreSQL, which supports unlimited <code class=\"docutils literal notranslate\">VARCHAR</code>\ncolumns.</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.StreamingHttpResponse\" title=\"django.http.StreamingHttpResponse\"><code class=\"xref py py-class docutils literal notranslate\">StreamingHttpResponse</code></a> now supports async iterators\nwhen Django is served via ASGI.</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>The <a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#cmdoption-test-debug-sql\"><code class=\"xref std std-option docutils literal notranslate\">test --debug-sql</code></a> option now formats SQL queries with\n<code class=\"docutils literal notranslate\">sqlparse</code>.</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\">headers</code>\nparameter, which accepts a dictionary of header names and values. This allows\na more natural syntax for declaring headers.</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=\"c1\"># Before:</span>\n<span class=\"bp\">self</span><span class=\"o\">.</span>client<span class=\"o\">.</span>get<span class=\"p\">(</span><span class=\"s2\">&quot;/home/&quot;</span><span class=\"p\">,</span> HTTP_ACCEPT_LANGUAGE<span class=\"o\">=</span><span class=\"s2\">&quot;fr&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>get<span class=\"p\">(</span><span class=\"s2\">&quot;/home/&quot;</span><span class=\"p\">,</span> ACCEPT_LANGUAGE<span class=\"o\">=</span><span class=\"s2\">&quot;fr&quot;</span><span class=\"p\">)</span>\n\n<span class=\"c1\"># After:</span>\n<span class=\"bp\">self</span><span class=\"o\">.</span>client<span class=\"o\">.</span>get<span class=\"p\">(</span><span class=\"s2\">&quot;/home/&quot;</span><span class=\"p\">,</span> headers<span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;accept-language&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;fr&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>get<span class=\"p\">(</span><span class=\"s2\">&quot;/home/&quot;</span><span class=\"p\">,</span> headers<span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;accept-language&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;fr&quot;</span><span class=\"p\">})</span>\n</code></pre></div>\n</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>The new <code class=\"docutils literal notranslate\">encoder</code> parameter for <a class=\"reference internal\" href=\"/en/dev/ref/utils/#django.utils.html.json_script\" title=\"django.utils.html.json_script\"><code class=\"xref py py-meth docutils literal notranslate\">django.utils.html.json_script()</code></a>\nfunction allows customizing a JSON encoder class.</p></li>\n<li><p>The private internal vendored copy of <code class=\"docutils literal notranslate\">urllib.parse.urlsplit()</code> now strips\n<code class=\"docutils literal notranslate\">'\\r'</code>, <code class=\"docutils literal notranslate\">'\\n'</code>, and <code class=\"docutils literal notranslate\">'\\t'</code> (see <span class=\"target\" id=\"index-2\"></span><a class=\"cve reference external\" href=\"https://www.cve.org/CVERecord?id=CVE-2022-0391\"><strong>CVE 2022-0391</strong></a> and <a class=\"extlink-bpo reference external\" href=\"https://bugs.python.org/issue?&#64;action=redirect&amp;bpo=43882\">bpo-43882</a>).\nThis is to protect projects that may be incorrectly using the internal\n<code class=\"docutils literal notranslate\">url_has_allowed_host_and_scheme()</code> function, instead of using one of the\ndocumented functions for handling URL redirects. The Django functions were\nnot affected.</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/ref/utils/#django.utils.http.content_disposition_header\" title=\"django.utils.http.content_disposition_header\"><code class=\"xref py py-func docutils literal notranslate\">django.utils.http.content_disposition_header()</code></a> function returns\na <code class=\"docutils literal notranslate\">Content-Disposition</code> HTTP header value as specified by <span class=\"target\" id=\"index-3\"></span><a class=\"rfc reference external\" href=\"https://datatracker.ietf.org/doc/html/rfc6266.html\"><strong>RFC 6266</strong></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 list of common passwords used by <code class=\"docutils literal notranslate\">CommonPasswordValidator</code> is updated\nto the most recent version.</p></li>\n</ul>\n</section>\n</section>\n</section>\n<section id=\"backwards-incompatible-changes-in-4-2\">\n<span id=\"backwards-incompatible-4-2\"></span><h2>Backwards incompatible changes in 4.2<a class=\"heading-anchor\" href=\"#backwards-incompatible-changes-in-4-2\"><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\">DatabaseFeatures.allows_group_by_pk</code> is removed as it only remained to\naccommodate a MySQL extension that has been supplanted by proper functional\ndependency detection in MySQL 5.7.15. Note that\n<code class=\"docutils literal notranslate\">DatabaseFeatures.allows_group_by_selected_pks</code> is still supported and\nshould be enabled if your backend supports functional dependency detection in\n<code class=\"docutils literal notranslate\">GROUP BY</code> clauses as specified by the <code class=\"docutils literal notranslate\">SQL:1999</code> standard.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#django-admin-inspectdb\"><code class=\"xref std std-djadmin docutils literal notranslate\">inspectdb</code></a> now uses <code class=\"docutils literal notranslate\">display_size</code> from\n<code class=\"docutils literal notranslate\">DatabaseIntrospection.get_table_description()</code> rather than\n<code class=\"docutils literal notranslate\">internal_size</code> for <code class=\"docutils literal notranslate\">CharField</code>.</p></li>\n</ul>\n</section>\n<section id=\"dropped-support-for-mariadb-10-3\">\n<h3>Dropped support for MariaDB 10.3<a class=\"heading-anchor\" href=\"#dropped-support-for-mariadb-10-3\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Upstream support for MariaDB 10.3 ends in May 2023. Django 4.2 supports MariaDB\n10.4 and higher.</p>\n</section>\n<section id=\"dropped-support-for-mysql-5-7\">\n<h3>Dropped support for MySQL 5.7<a class=\"heading-anchor\" href=\"#dropped-support-for-mysql-5-7\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Upstream support for MySQL 5.7 ends in October 2023. Django 4.2 supports MySQL\n8 and higher.</p>\n</section>\n<section id=\"dropped-support-for-postgresql-11\">\n<h3>Dropped support for PostgreSQL 11<a class=\"heading-anchor\" href=\"#dropped-support-for-postgresql-11\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Upstream support for PostgreSQL 11 ends in November 2023. Django 4.2 supports\nPostgreSQL 12 and higher.</p>\n</section>\n<section id=\"setting-update-fields-in-model-save-may-now-be-required\">\n<h3>Setting <code class=\"docutils literal notranslate\">update_fields</code> in <code class=\"docutils literal notranslate\">Model.save()</code> may now be required<a class=\"heading-anchor\" href=\"#setting-update-fields-in-model-save-may-now-be-required\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>In order to avoid updating unnecessary columns,\n<a class=\"reference internal\" href=\"/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.update_or_create\" title=\"django.db.models.query.QuerySet.update_or_create\"><code class=\"xref py py-meth docutils literal notranslate\">QuerySet.update_or_create()</code></a> now passes <code class=\"docutils literal notranslate\">update_fields</code> to the\n<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> calls. As a consequence, any\nfields modified in the custom <code class=\"docutils literal notranslate\">save()</code> methods should be added to the\n<code class=\"docutils literal notranslate\">update_fields</code> keyword argument before calling <code class=\"docutils literal notranslate\">super()</code>. See\n<a class=\"reference internal\" href=\"/en/dev/topics/db/models/#overriding-model-methods\"><span class=\"std std-ref\">Overriding predefined model methods</span></a> for more details.</p>\n</section>\n<section id=\"dropped-support-for-raw-aggregations-on-mysql\">\n<h3>Dropped support for raw aggregations on MySQL<a class=\"heading-anchor\" href=\"#dropped-support-for-raw-aggregations-on-mysql\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>MySQL 8+ allows functional dependencies on <code class=\"docutils literal notranslate\">GROUP BY</code> columns, so the\npre-Django 4.2 workaround of grouping by primary keys of the main table is\nremoved. As a consequence, using <code class=\"docutils literal notranslate\">RawSQL()</code> aggregations is no longer\nsupported on MySQL as there is no way to determine if such aggregations are\nneeded or valid in the <code class=\"docutils literal notranslate\">GROUP BY</code> clause. Use <a class=\"reference internal\" href=\"/en/dev/ref/models/querysets/#aggregation-functions\"><span class=\"std std-ref\">Aggregation functions</span></a>\ninstead.</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>The undocumented <code class=\"docutils literal notranslate\">django.http.multipartparser.parse_header()</code> function is\nremoved. Use <code class=\"docutils literal notranslate\">django.utils.http.parse_header_parameters()</code> instead.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/topics/i18n/translation/#std-templatetag-blocktranslate\"><code class=\"xref std std-ttag docutils literal notranslate\">{% blocktranslate asvar … %}</code></a> result is now marked as\nsafe for (HTML) output purposes.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">autofocus</code> HTML attribute in the admin search box is removed as it can\nbe confusing for screen readers.</p></li>\n<li><p>The <a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#cmdoption-makemigrations-check\"><code class=\"xref std std-option docutils literal notranslate\">makemigrations --check</code></a> option no longer creates missing\nmigration files.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">alias</code> argument for <a class=\"reference internal\" href=\"/en/dev/ref/models/expressions/#django.db.models.Expression.get_group_by_cols\" title=\"django.db.models.Expression.get_group_by_cols\"><code class=\"xref py py-meth docutils literal notranslate\">Expression.get_group_by_cols()</code></a> is removed.</p></li>\n<li><p>The minimum supported version of <code class=\"docutils literal notranslate\">sqlparse</code> is increased from 0.2.2 to\n0.3.1.</p></li>\n<li><p>The undocumented <code class=\"docutils literal notranslate\">negated</code> parameter of the\n<a class=\"reference internal\" href=\"/en/dev/ref/models/expressions/#django.db.models.Exists\" title=\"django.db.models.Exists\"><code class=\"xref py py-class docutils literal notranslate\">Exists</code></a> expression is removed.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">is_summary</code> argument of the undocumented <code class=\"docutils literal notranslate\">Query.add_annotation()</code>\nmethod is removed.</p></li>\n<li><p>The minimum supported version of SQLite is increased from 3.9.0 to 3.21.0.</p></li>\n<li><p>The minimum supported version of <code class=\"docutils literal notranslate\">asgiref</code> is increased from 3.5.2 to\n3.6.0.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/topics/auth/default/#django.contrib.auth.forms.UserCreationForm\" title=\"django.contrib.auth.forms.UserCreationForm\"><code class=\"xref py py-class docutils literal notranslate\">UserCreationForm</code></a> now rejects usernames\nthat differ only in case. If you need the previous behavior, use\n<a class=\"reference internal\" href=\"/en/dev/topics/auth/default/#django.contrib.auth.forms.BaseUserCreationForm\" title=\"django.contrib.auth.forms.BaseUserCreationForm\"><code class=\"xref py py-class docutils literal notranslate\">BaseUserCreationForm</code></a> instead.</p></li>\n<li><p>The minimum supported version of <code class=\"docutils literal notranslate\">mysqlclient</code> is increased from 1.4.0 to\n1.4.3.</p></li>\n<li><p>The minimum supported version of <code class=\"docutils literal notranslate\">argon2-cffi</code> is increased  from 19.1.0 to\n19.2.0.</p></li>\n<li><p>The minimum supported version of <code class=\"docutils literal notranslate\">Pillow</code> is increased from 6.2.0 to 6.2.1.</p></li>\n<li><p>The minimum supported version of <code class=\"docutils literal notranslate\">jinja2</code> is increased from 2.9.2 to\n2.11.0.</p></li>\n<li><p>The minimum supported version of <a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/redis/\">redis-py</a> is increased from\n3.0.0 to 3.4.0.</p></li>\n<li><p>Manually instantiated <code class=\"docutils literal notranslate\">WSGIRequest</code> objects must be provided a file-like\nobject for <code class=\"docutils literal notranslate\">wsgi.input</code>. Previously, Django was more lax than the expected\nbehavior as specified by the WSGI specification.</p></li>\n<li><p>Support for <code class=\"docutils literal notranslate\">PROJ</code> &lt; 5 is removed.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/topics/email/#topic-email-smtp-backend\"><span class=\"std std-ref\">SMTP EmailBackend</span></a> now verifies a\n<a class=\"reference external\" href=\"https://docs.python.org/3/library/ssl.html#ssl.SSLContext.check_hostname\" title=\"(in Python v3.14)\"><code class=\"xref py py-attr docutils literal notranslate\">hostname</code></a> and\n<a class=\"reference external\" href=\"https://docs.python.org/3/library/ssl.html#ssl.SSLContext.verify_mode\" title=\"(in Python v3.14)\"><code class=\"xref py py-attr docutils literal notranslate\">certificates</code></a>. If you need the\nprevious behavior that is less restrictive and not recommended, subclass\n<code class=\"docutils literal notranslate\">EmailBackend</code> and override the <code class=\"docutils literal notranslate\">ssl_context</code> property.</p></li>\n</ul>\n</section>\n</section>\n<section id=\"features-deprecated-in-4-2\">\n<span id=\"deprecated-features-4-2\"></span><h2>Features deprecated in 4.2<a class=\"heading-anchor\" href=\"#features-deprecated-in-4-2\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"index-together-option-is-deprecated-in-favor-of-indexes\">\n<h3><code class=\"docutils literal notranslate\">index_together</code> option is deprecated in favor of <code class=\"docutils literal notranslate\">indexes</code><a class=\"heading-anchor\" href=\"#index-together-option-is-deprecated-in-favor-of-indexes\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The <code class=\"docutils literal notranslate\">Meta.index_together</code> option is deprecated in favor of 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\">indexes</code></a> option.</p>\n<p>Migrating existing <code class=\"docutils literal notranslate\">index_together</code> should be handled as a migration. 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\">Author</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    rank <span class=\"o\">=</span> models<span class=\"o\">.</span>IntegerField<span class=\"p\">()</span>\n    name <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">30</span><span class=\"p\">)</span>\n\n    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        index_together <span class=\"o\">=</span> <span class=\"p\">[[</span><span class=\"s2\">&quot;rank&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;name&quot;</span><span class=\"p\">]]</span>\n</code></pre></div>\n<p>Should become:</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\">Author</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    rank <span class=\"o\">=</span> models<span class=\"o\">.</span>IntegerField<span class=\"p\">()</span>\n    name <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">30</span><span class=\"p\">)</span>\n\n    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        indexes <span class=\"o\">=</span> <span class=\"p\">[</span>models<span class=\"o\">.</span>Index<span class=\"p\">(</span>fields<span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s2\">&quot;rank&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;name&quot;</span><span class=\"p\">])]</span>\n</code></pre></div>\n<p>Running 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 will generate a migration\ncontaining a <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\nwhich will rename the existing index. Next, consider squashing migrations to\nremove <code class=\"docutils literal notranslate\">index_together</code> from historical migrations.</p>\n<p>The <code class=\"docutils literal notranslate\">AlterIndexTogether</code> migration operation is now officially supported only\nfor pre-Django 4.2 migration files. For backward compatibility reasons, it’s\nstill part of the public API, and there’s no plan to deprecate or remove it,\nbut it should not be used for new migrations. Use\n<a class=\"reference internal\" href=\"/en/dev/ref/migration-operations/#django.db.migrations.operations.AddIndex\" title=\"django.db.migrations.operations.AddIndex\"><code class=\"xref py py-class docutils literal notranslate\">AddIndex</code></a> and\n<a class=\"reference internal\" href=\"/en/dev/ref/migration-operations/#django.db.migrations.operations.RemoveIndex\" title=\"django.db.migrations.operations.RemoveIndex\"><code class=\"xref py py-class docutils literal notranslate\">RemoveIndex</code></a> operations instead.</p>\n</section>\n<section id=\"passing-encoded-json-string-literals-to-jsonfield-is-deprecated\">\n<h3>Passing encoded JSON string literals to <code class=\"docutils literal notranslate\">JSONField</code> is deprecated<a class=\"heading-anchor\" href=\"#passing-encoded-json-string-literals-to-jsonfield-is-deprecated\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><code class=\"docutils literal notranslate\">JSONField</code> and its associated lookups and aggregates used to allow passing\nJSON encoded string literals which caused ambiguity on whether string literals\nwere already encoded from database backend’s perspective.</p>\n<p>During the deprecation period string literals will be attempted to be JSON\ndecoded and a warning will be emitted on success that points at passing\nnon-encoded forms instead.</p>\n<p>Code that used to pass JSON encoded string literals:</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>Document<span class=\"o\">.</span>objects<span class=\"o\">.</span>bulk_create<span class=\"p\">(</span>\n    Document<span class=\"p\">(</span>data<span class=\"o\">=</span>Value<span class=\"p\">(</span><span class=\"s2\">&quot;null&quot;</span><span class=\"p\">)),</span>\n    Document<span class=\"p\">(</span>data<span class=\"o\">=</span>Value<span class=\"p\">(</span><span class=\"s2\">&quot;[]&quot;</span><span class=\"p\">)),</span>\n    Document<span class=\"p\">(</span>data<span class=\"o\">=</span>Value<span class=\"p\">(</span><span class=\"s1\">&#39;&quot;foo-bar&quot;&#39;</span><span class=\"p\">)),</span>\n<span class=\"p\">)</span>\nDocument<span class=\"o\">.</span>objects<span class=\"o\">.</span>annotate<span class=\"p\">(</span>\n    JSONBAgg<span class=\"p\">(</span><span class=\"s2\">&quot;field&quot;</span><span class=\"p\">,</span> default<span class=\"o\">=</span>Value<span class=\"p\">(</span><span class=\"s2\">&quot;[]&quot;</span><span class=\"p\">)),</span>\n<span class=\"p\">)</span>\n</code></pre></div>\n<p>Should become:</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>Document<span class=\"o\">.</span>objects<span class=\"o\">.</span>bulk_create<span class=\"p\">(</span>\n    Document<span class=\"p\">(</span>data<span class=\"o\">=</span>Value<span class=\"p\">(</span><span class=\"kc\">None</span><span class=\"p\">,</span> JSONField<span class=\"p\">())),</span>\n    Document<span class=\"p\">(</span>data<span class=\"o\">=</span><span class=\"p\">[]),</span>\n    Document<span class=\"p\">(</span>data<span class=\"o\">=</span><span class=\"s2\">&quot;foo-bar&quot;</span><span class=\"p\">),</span>\n<span class=\"p\">)</span>\nDocument<span class=\"o\">.</span>objects<span class=\"o\">.</span>annotate<span class=\"p\">(</span>\n    JSONBAgg<span class=\"p\">(</span><span class=\"s2\">&quot;field&quot;</span><span class=\"p\">,</span> default<span class=\"o\">=</span><span class=\"p\">[]),</span>\n<span class=\"p\">)</span>\n</code></pre></div>\n<p>From Django 5.1+ string literals will be implicitly interpreted as JSON string\nliterals.</p>\n</section>\n<section id=\"id1\">\n<h3>Miscellaneous<a class=\"heading-anchor\" href=\"#id1\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<ul>\n<li><p>The <code class=\"docutils literal notranslate\">BaseUserManager.make_random_password()</code> method is deprecated. See\n<a class=\"reference external\" href=\"https://docs.python.org/3/library/secrets.html#recipes-and-best-practices\">recipes and best practices</a>\nfor using Python’s <a class=\"reference external\" href=\"https://docs.python.org/3/library/secrets.html#module-secrets\" title=\"(in Python v3.14)\"><code class=\"xref py py-mod docutils literal notranslate\">secrets</code></a> module to generate passwords.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">length_is</code> template filter is deprecated in favor of <a class=\"reference internal\" href=\"/en/dev/ref/templates/builtins/#std-templatefilter-length\"><code class=\"xref std std-tfilter docutils literal notranslate\">length</code></a>\nand the <code class=\"docutils literal notranslate\">==</code> operator within an <a class=\"reference internal\" href=\"/en/dev/ref/templates/builtins/#std-templatetag-if\"><code class=\"xref std std-ttag docutils literal notranslate\">{% if %}</code></a> tag. For example</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=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">value</span><span class=\"o\">|</span><span class=\"nf\">length</span> <span class=\"o\">==</span> <span class=\"m\">4</span> <span class=\"cp\">%}</span>…<span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span>\n<span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">value</span><span class=\"o\">|</span><span class=\"nf\">length</span> <span class=\"o\">==</span> <span class=\"m\">4</span> <span class=\"cp\">%}</span>True<span class=\"cp\">{%</span> <span class=\"k\">else</span> <span class=\"cp\">%}</span>False<span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>instead of:</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=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">value</span><span class=\"o\">|</span><span class=\"nf\">length_is</span><span class=\"o\">:</span><span class=\"m\">4</span> <span class=\"cp\">%}</span>…<span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span>\n<span class=\"cp\">{{</span> <span class=\"nv\">value</span><span class=\"o\">|</span><span class=\"nf\">length_is</span><span class=\"o\">:</span><span class=\"m\">4</span> <span class=\"cp\">}}</span>\n</code></pre></div>\n</li>\n<li><p><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 deprecated.</p></li>\n<li><p><code class=\"docutils literal notranslate\">django.contrib.postgres.fields.CICharField</code> is deprecated in favor of\n<code class=\"docutils literal notranslate\">CharField(db_collation=&quot;…&quot;)</code> with a case-insensitive non-deterministic\ncollation.</p></li>\n<li><p><code class=\"docutils literal notranslate\">django.contrib.postgres.fields.CIEmailField</code> is deprecated in favor of\n<code class=\"docutils literal notranslate\">EmailField(db_collation=&quot;…&quot;)</code> with a case-insensitive non-deterministic\ncollation.</p></li>\n<li><p><code class=\"docutils literal notranslate\">django.contrib.postgres.fields.CITextField</code> is deprecated in favor of\n<code class=\"docutils literal notranslate\">TextField(db_collation=&quot;…&quot;)</code> with a case-insensitive non-deterministic\ncollation.</p></li>\n<li><p><code class=\"docutils literal notranslate\">django.contrib.postgres.fields.CIText</code> mixin is deprecated.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">map_height</code> and <code class=\"docutils literal notranslate\">map_width</code> attributes of <code class=\"docutils literal notranslate\">BaseGeometryWidget</code> are\ndeprecated, use CSS to size map widgets instead.</p></li>\n<li><p><code class=\"docutils literal notranslate\">SimpleTestCase.assertFormsetError()</code> is deprecated in favor of\n<code class=\"docutils literal notranslate\">assertFormSetError()</code>.</p></li>\n<li><p><code class=\"docutils literal notranslate\">TransactionTestCase.assertQuerysetEqual()</code> is deprecated in favor of\n<code class=\"docutils literal notranslate\">assertQuerySetEqual()</code>.</p></li>\n<li><p>Passing positional arguments to <code class=\"docutils literal notranslate\">Signer</code> and <code class=\"docutils literal notranslate\">TimestampSigner</code> is\ndeprecated in favor of keyword-only arguments.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">DEFAULT_FILE_STORAGE</code> setting is deprecated in favor of\n<code class=\"docutils literal notranslate\">STORAGES[&quot;default&quot;]</code>.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">STATICFILES_STORAGE</code> setting is deprecated in favor of\n<code class=\"docutils literal notranslate\">STORAGES[&quot;staticfiles&quot;]</code>.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">django.core.files.storage.get_storage_class()</code> function is deprecated.</p></li>\n</ul>\n</section>\n</section>","rootId":"django-4-2-release-notes","toc":[{"title":"Python compatibility","anchor":"python-compatibility","children":[]},{"title":"What’s new in Django 4.2","anchor":"what-s-new-in-django-4-2","children":[{"title":"Psycopg 3 support","anchor":"psycopg-3-support","children":[]},{"title":"Comments on columns and tables","anchor":"comments-on-columns-and-tables","children":[]},{"title":"Mitigation for the BREACH attack","anchor":"mitigation-for-the-breach-attack","children":[]},{"title":"In-memory file storage","anchor":"in-memory-file-storage","children":[]},{"title":"Custom file storages","anchor":"custom-file-storages","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":"Error Reporting","anchor":"error-reporting","children":[]},{"title":"Forms","anchor":"forms","children":[]},{"title":"Internationalization","anchor":"internationalization","children":[]},{"title":"Logging","anchor":"logging","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":"Tests","anchor":"tests","children":[]},{"title":"Utilities","anchor":"utilities","children":[]},{"title":"Validators","anchor":"validators","children":[]}]}]},{"title":"Backwards incompatible changes in 4.2","anchor":"backwards-incompatible-changes-in-4-2","children":[{"title":"Database backend API","anchor":"database-backend-api","children":[]},{"title":"Dropped support for MariaDB 10.3","anchor":"dropped-support-for-mariadb-10-3","children":[]},{"title":"Dropped support for MySQL 5.7","anchor":"dropped-support-for-mysql-5-7","children":[]},{"title":"Dropped support for PostgreSQL 11","anchor":"dropped-support-for-postgresql-11","children":[]},{"title":"Setting update_fields in Model.save() may now be required","anchor":"setting-update-fields-in-model-save-may-now-be-required","children":[]},{"title":"Dropped support for raw aggregations on MySQL","anchor":"dropped-support-for-raw-aggregations-on-mysql","children":[]},{"title":"Miscellaneous","anchor":"miscellaneous","children":[]}]},{"title":"Features deprecated in 4.2","anchor":"features-deprecated-in-4-2","children":[{"title":"index_together option is deprecated in favor of indexes","anchor":"index-together-option-is-deprecated-in-favor-of-indexes","children":[]},{"title":"Passing encoded JSON string literals to JSONField is deprecated","anchor":"passing-encoded-json-string-literals-to-jsonfield-is-deprecated","children":[]},{"title":"Miscellaneous","anchor":"id1","children":[]}]}],"breadcrumbs":[{"docname":"releases/index","title":"Release notes","url":"/en/dev/releases/"}],"prev":{"docname":"releases/4.2.1","title":"Django 4.2.1 release notes","url":"/en/dev/releases/4.2.1/"},"next":{"docname":"releases/4.1.13","title":"Django 4.1.13 release notes","url":"/en/dev/releases/4.1.13/"},"formats":{"html":"/en/dev/releases/4.2/","markdown":"/en/dev/releases/4.2.md","json":"/en/dev/releases/4.2.json"},"source":"https://github.com/django/django/blob/main/docs/releases/4.2.txt","official":"https://docs.djangoproject.com/en/dev/releases/4.2/","inVersions":["dev","6.1","6.0","5.2","5.1","5.0","4.2"],"inLocales":["en"]}