{"title":"Django 2.2 release notes","version":"dev","locale":"en","docname":"releases/2.2","url":"/en/dev/releases/2.2/","canonical":"https://djangodocs.dev/en/dev/releases/2.2/","summary":"Welcome to Django 2.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 2.2 release notes<a class=\"heading-anchor\" href=\"#django-2-2-release-notes\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p><em>April 1, 2019</em></p>\n<p>Welcome to Django 2.2!</p>\n<p>These release notes cover the <a class=\"reference internal\" href=\"#whats-new-2-2\"><span class=\"std std-ref\">new features</span></a>, as well as\nsome <a class=\"reference internal\" href=\"#backwards-incompatible-2-2\"><span class=\"std std-ref\">backwards incompatible changes</span></a> you’ll\nwant to be aware of when upgrading from Django 2.1 or earlier. We’ve\n<a class=\"reference internal\" href=\"#deprecated-features-2-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 2.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 1.11, will\nend in April 2020.</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 2.2 supports Python 3.5, 3.6, 3.7, 3.8 (as of 2.2.8), and 3.9 (as of\n2.2.17). We <strong>highly recommend</strong> and only officially support the latest release\nof each series.</p>\n</section>\n<section id=\"what-s-new-in-django-2-2\">\n<span id=\"whats-new-2-2\"></span><h2>What’s new in Django 2.2<a class=\"heading-anchor\" href=\"#what-s-new-in-django-2-2\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"constraints\">\n<h3>Constraints<a class=\"heading-anchor\" href=\"#constraints\"><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/constraints/#django.db.models.CheckConstraint\" title=\"django.db.models.CheckConstraint\"><code class=\"xref py py-class docutils literal notranslate\">CheckConstraint</code></a> and\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\">UniqueConstraint</code></a> classes enable adding custom\ndatabase constraints. Constraints are added to models using the\n<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.</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>Added a CSS class to the column headers of\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/admin/#django.contrib.admin.TabularInline\" title=\"django.contrib.admin.TabularInline\"><code class=\"xref py py-class docutils literal notranslate\">TabularInline</code></a>.</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 <code class=\"docutils literal notranslate\">HttpRequest</code> is now passed as the first positional argument to\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>, if it accepts it.</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>Added Oracle support for the\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/functions/#django.contrib.gis.db.models.functions.Envelope\" title=\"django.contrib.gis.db.models.functions.Envelope\"><code class=\"xref py py-class docutils literal notranslate\">Envelope</code></a> function.</p></li>\n<li><p>Added SpatiaLite support for the <a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/geoquerysets/#std-fieldlookup-coveredby\"><code class=\"xref std std-lookup docutils literal notranslate\">coveredby</code></a> and <a class=\"reference internal\" href=\"/en/dev/ref/contrib/gis/geoquerysets/#std-fieldlookup-covers\"><code class=\"xref std std-lookup docutils literal notranslate\">covers</code></a>\nlookups.</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 <code class=\"docutils literal notranslate\">ordering</code> argument for\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/aggregates/#django.contrib.postgres.aggregates.ArrayAgg\" title=\"django.contrib.postgres.aggregates.ArrayAgg\"><code class=\"xref py py-class docutils literal notranslate\">ArrayAgg</code></a> and\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/aggregates/#django.contrib.postgres.aggregates.StringAgg\" title=\"django.contrib.postgres.aggregates.StringAgg\"><code class=\"xref py py-class docutils literal notranslate\">StringAgg</code></a> determines the\nordering of the aggregated elements.</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/indexes/#django.contrib.postgres.indexes.BTreeIndex\" title=\"django.contrib.postgres.indexes.BTreeIndex\"><code class=\"xref py py-class docutils literal notranslate\">BTreeIndex</code></a>,\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/indexes/#django.contrib.postgres.indexes.HashIndex\" title=\"django.contrib.postgres.indexes.HashIndex\"><code class=\"xref py py-class docutils literal notranslate\">HashIndex</code></a> and\n<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> classes allow\ncreating <code class=\"docutils literal notranslate\">B-Tree</code>, <code class=\"docutils literal notranslate\">hash</code>, and <code class=\"docutils literal notranslate\">SP-GiST</code> indexes in the database.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/indexes/#django.contrib.postgres.indexes.BrinIndex\" title=\"django.contrib.postgres.indexes.BrinIndex\"><code class=\"xref py py-class docutils literal notranslate\">BrinIndex</code></a> now has the\n<code class=\"docutils literal notranslate\">autosummarize</code> parameter.</p></li>\n<li><p>The new <code class=\"docutils literal notranslate\">search_type</code> parameter of\n<a class=\"reference internal\" href=\"/en/dev/ref/contrib/postgres/search/#django.contrib.postgres.search.SearchQuery\" title=\"django.contrib.postgres.search.SearchQuery\"><code class=\"xref py py-class docutils literal notranslate\">SearchQuery</code></a> allows searching for\na phrase or raw expression.</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>Added path matching to the <a class=\"reference internal\" href=\"/en/dev/ref/contrib/staticfiles/#cmdoption-collectstatic-ignore\"><code class=\"xref std std-option docutils literal notranslate\">collectstatic --ignore</code></a> option so that\npatterns like <code class=\"docutils literal notranslate\">/vendor/*.js</code> can be used.</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>Added result streaming for <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> on SQLite.</p></li>\n</ul>\n</section>\n<section id=\"generic-views\">\n<h4>Generic Views<a class=\"heading-anchor\" href=\"#generic-views\"><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/class-based-views/base/#django.views.generic.base.View.setup\" title=\"django.views.generic.base.View.setup\"><code class=\"xref py py-meth docutils literal notranslate\">View.setup</code></a> hook\ninitializes view attributes before calling\n<a class=\"reference internal\" href=\"/en/dev/ref/class-based-views/base/#django.views.generic.base.View.dispatch\" title=\"django.views.generic.base.View.dispatch\"><code class=\"xref py py-meth docutils literal notranslate\">dispatch()</code></a>. It allows mixins to set up\ninstance attributes for reuse in child classes.</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 Armenian language.</p></li>\n</ul>\n</section>\n<section id=\"management-commands\">\n<h4>Management Commands<a class=\"heading-anchor\" href=\"#management-commands\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<ul class=\"simple\">\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#cmdoption-force-color\"><code class=\"xref std std-option docutils literal notranslate\">--force-color</code></a> option forces colorization of the command\noutput.</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 creates models for foreign tables on PostgreSQL.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#cmdoption-inspectdb-include-views\"><code class=\"xref std std-option docutils literal notranslate\">inspectdb --include-views</code></a> now creates models for materialized views\non Oracle and PostgreSQL.</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#cmdoption-inspectdb-include-partitions\"><code class=\"xref std std-option docutils literal notranslate\">inspectdb --include-partitions</code></a> option allows creating\nmodels for partition tables on PostgreSQL. In older versions, models are\ncreated child tables instead the parent.</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 introspects <a class=\"reference internal\" href=\"/en/dev/ref/models/fields/#django.db.models.DurationField\" title=\"django.db.models.DurationField\"><code class=\"xref py py-class docutils literal notranslate\">DurationField</code></a>\nfor Oracle and PostgreSQL, and <a class=\"reference internal\" href=\"/en/dev/ref/models/fields/#django.db.models.AutoField\" title=\"django.db.models.AutoField\"><code class=\"xref py py-class docutils literal notranslate\">AutoField</code></a> for\nSQLite.</p></li>\n<li><p>On Oracle, <a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#django-admin-dbshell\"><code class=\"xref std std-djadmin docutils literal notranslate\">dbshell</code></a> is wrapped with <code class=\"docutils literal notranslate\">rlwrap</code>, if available.\n<code class=\"docutils literal notranslate\">rlwrap</code> provides a command history and editing of keyboard input.</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#cmdoption-makemigrations-no-header\"><code class=\"xref std std-option docutils literal notranslate\">makemigrations --no-header</code></a> option avoids writing header\ncomments in generated migration file(s). This option is also available for\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>.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#django-admin-runserver\"><code class=\"xref std std-djadmin docutils literal notranslate\">runserver</code></a> can now use <a class=\"reference external\" href=\"https://facebook.github.io/watchman/\">Watchman</a> to improve the performance of\nwatching a large number of files for changes.</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/django-admin/#cmdoption-migrate-plan\"><code class=\"xref std std-option docutils literal notranslate\">migrate --plan</code></a> option prints the list of migration\noperations that will be performed.</p></li>\n<li><p><code class=\"docutils literal notranslate\">NoneType</code> can now be serialized in migrations.</p></li>\n<li><p>You can now <a class=\"reference internal\" href=\"/en/dev/topics/migrations/#custom-migration-serializers\"><span class=\"std std-ref\">register custom serializers</span></a>\nfor migrations.</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>Added support for PostgreSQL operator classes (<a class=\"reference internal\" href=\"/en/dev/ref/models/indexes/#django.db.models.Index.opclasses\" title=\"django.db.models.Index.opclasses\"><code class=\"xref py py-attr docutils literal notranslate\">Index.opclasses</code></a>).</p></li>\n<li><p>Added support for partial indexes (<a class=\"reference internal\" href=\"/en/dev/ref/models/indexes/#django.db.models.Index.condition\" title=\"django.db.models.Index.condition\"><code class=\"xref py py-attr docutils literal notranslate\">Index.condition</code></a>).</p></li>\n<li><p>Added the <a class=\"reference internal\" href=\"/en/dev/ref/models/database-functions/#django.db.models.functions.NullIf\" title=\"django.db.models.functions.NullIf\"><code class=\"xref py py-class docutils literal notranslate\">NullIf</code></a> and\n<a class=\"reference internal\" href=\"/en/dev/ref/models/database-functions/#django.db.models.functions.Reverse\" title=\"django.db.models.functions.Reverse\"><code class=\"xref py py-class docutils literal notranslate\">Reverse</code></a> database functions, as well as\nmany <a class=\"reference internal\" href=\"/en/dev/ref/models/database-functions/#math-functions\"><span class=\"std std-ref\">math database functions</span></a>.</p></li>\n<li><p>Setting the new <code class=\"docutils literal notranslate\">ignore_conflicts</code> parameter of\n<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> to <code class=\"docutils literal notranslate\">True</code> tells the database to ignore\nfailure to insert rows that fail uniqueness constraints or other checks.</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/ref/models/database-functions/#django.db.models.functions.ExtractIsoYear\" title=\"django.db.models.functions.ExtractIsoYear\"><code class=\"xref py py-class docutils literal notranslate\">ExtractIsoYear</code></a> function extracts\nISO-8601 week-numbering years from <a class=\"reference internal\" href=\"/en/dev/ref/models/fields/#django.db.models.DateField\" title=\"django.db.models.DateField\"><code class=\"xref py py-class docutils literal notranslate\">DateField</code></a> and\n<a class=\"reference internal\" href=\"/en/dev/ref/models/fields/#django.db.models.DateTimeField\" title=\"django.db.models.DateTimeField\"><code class=\"xref py py-class docutils literal notranslate\">DateTimeField</code></a>, and the new <a class=\"reference internal\" href=\"/en/dev/ref/models/querysets/#std-fieldlookup-iso_year\"><code class=\"xref std std-lookup docutils literal notranslate\">iso_year</code></a>\nlookup allows querying by an ISO-8601 week-numbering year.</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.bulk_update\" title=\"django.db.models.query.QuerySet.bulk_update\"><code class=\"xref py py-meth docutils literal notranslate\">QuerySet.bulk_update()</code></a> method allows efficiently updating\nspecific fields on multiple model instances.</p></li>\n<li><p>Django no longer always starts a transaction when a single query is being\nperformed, such as <code class=\"docutils literal notranslate\">Model.save()</code>, <code class=\"docutils literal notranslate\">QuerySet.update()</code>, and\n<code class=\"docutils literal notranslate\">Model.delete()</code>. This improves the performance of autocommit by reducing\nthe number of database round trips.</p></li>\n<li><p>Added SQLite support for the <a class=\"reference internal\" href=\"/en/dev/ref/models/querysets/#django.db.models.StdDev\" title=\"django.db.models.StdDev\"><code class=\"xref py py-class docutils literal notranslate\">StdDev</code></a> and\n<a class=\"reference internal\" href=\"/en/dev/ref/models/querysets/#django.db.models.Variance\" title=\"django.db.models.Variance\"><code class=\"xref py py-class docutils literal notranslate\">Variance</code></a> functions.</p></li>\n<li><p>The handling of <code class=\"docutils literal notranslate\">DISTINCT</code> aggregation is added to the\n<a class=\"reference internal\" href=\"/en/dev/ref/models/expressions/#django.db.models.Aggregate\" title=\"django.db.models.Aggregate\"><code class=\"xref py py-class docutils literal notranslate\">Aggregate</code></a> class. Adding <a class=\"reference internal\" href=\"/en/dev/ref/models/expressions/#django.db.models.Aggregate.allow_distinct\" title=\"django.db.models.Aggregate.allow_distinct\"><code class=\"xref py py-attr docutils literal notranslate\">allow_distinct =\nTrue</code></a> as a class attribute on\n<code class=\"docutils literal notranslate\">Aggregate</code> subclasses allows a <code class=\"docutils literal notranslate\">distinct</code> keyword argument to be\nspecified on initialization to ensure that the aggregate function is only\ncalled for each distinct value of <code class=\"docutils literal notranslate\">expressions</code>.</p></li>\n<li><p>The <a class=\"reference internal\" href=\"/en/dev/ref/models/relations/#django.db.models.fields.related.RelatedManager.add\" title=\"django.db.models.fields.related.RelatedManager.add\"><code class=\"xref py py-meth docutils literal notranslate\">RelatedManager.add()</code></a>, <a class=\"reference internal\" href=\"/en/dev/ref/models/relations/#django.db.models.fields.related.RelatedManager.create\" title=\"django.db.models.fields.related.RelatedManager.create\"><code class=\"xref py py-meth docutils literal notranslate\">create()</code></a>,\n<a class=\"reference internal\" href=\"/en/dev/ref/models/relations/#django.db.models.fields.related.RelatedManager.remove\" title=\"django.db.models.fields.related.RelatedManager.remove\"><code class=\"xref py py-meth docutils literal notranslate\">remove()</code></a>,  <a class=\"reference internal\" href=\"/en/dev/ref/models/relations/#django.db.models.fields.related.RelatedManager.set\" title=\"django.db.models.fields.related.RelatedManager.set\"><code class=\"xref py py-meth docutils literal notranslate\">set()</code></a>,\n<code class=\"docutils literal notranslate\">get_or_create()</code>, and <code class=\"docutils literal notranslate\">update_or_create()</code> methods are now allowed on\nmany-to-many relationships with intermediate models. The new\n<code class=\"docutils literal notranslate\">through_defaults</code> argument is used to specify values for new intermediate\nmodel instance(s).</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>Added <a class=\"reference internal\" href=\"/en/dev/ref/request-response/#django.http.HttpRequest.headers\" title=\"django.http.HttpRequest.headers\"><code class=\"xref py py-attr docutils literal notranslate\">HttpRequest.headers</code></a> to allow simple access to a request’s\nheaders.</p></li>\n</ul>\n</section>\n<section id=\"serialization\">\n<h4>Serialization<a class=\"heading-anchor\" href=\"#serialization\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<ul class=\"simple\">\n<li><p>You can now deserialize data using natural keys containing <a class=\"reference internal\" href=\"/en/dev/topics/serialization/#natural-keys-and-forward-references\"><span class=\"std std-ref\">forward\nreferences</span></a> by passing\n<code class=\"docutils literal notranslate\">handle_forward_references=True</code> to <code class=\"docutils literal notranslate\">serializers.deserialize()</code>.\nAdditionally, <a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#django-admin-loaddata\"><code class=\"xref std std-djadmin docutils literal notranslate\">loaddata</code></a> handles forward references automatically.</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 new <a class=\"reference internal\" href=\"/en/dev/topics/testing/tools/#django.test.SimpleTestCase.assertURLEqual\" title=\"django.test.SimpleTestCase.assertURLEqual\"><code class=\"xref py py-meth docutils literal notranslate\">SimpleTestCase.assertURLEqual()</code></a> assertion checks for a given\nURL, ignoring the ordering of the query string.\n<a class=\"reference internal\" href=\"/en/dev/topics/testing/tools/#django.test.SimpleTestCase.assertRedirects\" title=\"django.test.SimpleTestCase.assertRedirects\"><code class=\"xref py py-meth docutils literal notranslate\">assertRedirects()</code></a> uses the new assertion.</p></li>\n<li><p>The test <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> now supports automatic JSON\nserialization of list and tuple <code class=\"docutils literal notranslate\">data</code> when\n<code class=\"docutils literal notranslate\">content_type='application/json'</code>.</p></li>\n<li><p>The new <a class=\"reference internal\" href=\"/en/dev/ref/settings/#std-setting-TEST_ORACLE_MANAGED_FILES\"><code class=\"xref std std-setting docutils literal notranslate\">ORACLE_MANAGED_FILES</code></a> test\ndatabase setting allows using Oracle Managed Files (OMF) tablespaces.</p></li>\n<li><p>Deferrable database constraints are now checked at the end of each\n<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\">TestCase</code></a> test on SQLite 3.20+, just like on other\nbackends that support deferrable constraints. These checks aren’t implemented\nfor older versions of SQLite because they would require expensive table\nintrospection there.</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 skips the setup of databases\nnot <a class=\"reference internal\" href=\"/en/dev/topics/testing/tools/#testing-multi-db\"><span class=\"std std-ref\">referenced by tests</span></a>.</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.route\" title=\"django.urls.ResolverMatch.route\"><code class=\"xref py py-attr docutils literal notranslate\">ResolverMatch.route</code></a> attribute stores the route of the\nmatching URL pattern.</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><a class=\"reference internal\" href=\"/en/dev/ref/validators/#django.core.validators.MaxValueValidator\" title=\"django.core.validators.MaxValueValidator\"><code class=\"xref py py-class docutils literal notranslate\">MaxValueValidator</code></a>, <a class=\"reference internal\" href=\"/en/dev/ref/validators/#django.core.validators.MinValueValidator\" title=\"django.core.validators.MinValueValidator\"><code class=\"xref py py-class docutils literal notranslate\">MinValueValidator</code></a>,\n<a class=\"reference internal\" href=\"/en/dev/ref/validators/#django.core.validators.MinLengthValidator\" title=\"django.core.validators.MinLengthValidator\"><code class=\"xref py py-class docutils literal notranslate\">MinLengthValidator</code></a>, and <a class=\"reference internal\" href=\"/en/dev/ref/validators/#django.core.validators.MaxLengthValidator\" title=\"django.core.validators.MaxLengthValidator\"><code class=\"xref py py-class docutils literal notranslate\">MaxLengthValidator</code></a> now accept\na callable <code class=\"docutils literal notranslate\">limit_value</code>.</p></li>\n</ul>\n</section>\n</section>\n</section>\n<section id=\"backwards-incompatible-changes-in-2-2\">\n<span id=\"backwards-incompatible-2-2\"></span><h2>Backwards incompatible changes in 2.2<a class=\"heading-anchor\" href=\"#backwards-incompatible-changes-in-2-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>Third-party database backends must implement support for table check\nconstraints or set <code class=\"docutils literal notranslate\">DatabaseFeatures.supports_table_check_constraints</code> to\n<code class=\"docutils literal notranslate\">False</code>.</p></li>\n<li><p>Third party database backends must implement support for ignoring\nconstraints or uniqueness errors while inserting or set\n<code class=\"docutils literal notranslate\">DatabaseFeatures.supports_ignore_conflicts</code> to <code class=\"docutils literal notranslate\">False</code>.</p></li>\n<li><p>Third party database backends must implement introspection for\n<code class=\"docutils literal notranslate\">DurationField</code> or set <code class=\"docutils literal notranslate\">DatabaseFeatures.can_introspect_duration_field</code>\nto <code class=\"docutils literal notranslate\">False</code>.</p></li>\n<li><p><code class=\"docutils literal notranslate\">DatabaseFeatures.uses_savepoints</code> now defaults to <code class=\"docutils literal notranslate\">True</code>.</p></li>\n<li><p>Third party database backends must implement support for partial indexes or\nset <code class=\"docutils literal notranslate\">DatabaseFeatures.supports_partial_indexes</code> to <code class=\"docutils literal notranslate\">False</code>.</p></li>\n<li><p><code class=\"docutils literal notranslate\">DatabaseIntrospection.table_name_converter()</code> and\n<code class=\"docutils literal notranslate\">column_name_converter()</code> are removed. Third party database backends may\nneed to instead implement <code class=\"docutils literal notranslate\">DatabaseIntrospection.identifier_converter()</code>.\nIn that case, the constraint names that\n<code class=\"docutils literal notranslate\">DatabaseIntrospection.get_constraints()</code> returns must be normalized by\n<code class=\"docutils literal notranslate\">identifier_converter()</code>.</p></li>\n<li><p>SQL generation for indexes is moved from <a class=\"reference internal\" href=\"/en/dev/ref/models/indexes/#django.db.models.Index\" title=\"django.db.models.Index\"><code class=\"xref py py-class docutils literal notranslate\">Index</code></a> to\n<code class=\"docutils literal notranslate\">SchemaEditor</code> and these <code class=\"docutils literal notranslate\">SchemaEditor</code> methods are added:</p>\n<ul>\n<li><p><code class=\"docutils literal notranslate\">_create_primary_key_sql()</code> and <code class=\"docutils literal notranslate\">_delete_primary_key_sql()</code></p></li>\n<li><p><code class=\"docutils literal notranslate\">_delete_index_sql()</code> (to pair with <code class=\"docutils literal notranslate\">_create_index_sql()</code>)</p></li>\n<li><p><code class=\"docutils literal notranslate\">_delete_unique_sql</code> (to pair with <code class=\"docutils literal notranslate\">_create_unique_sql()</code>)</p></li>\n<li><p><code class=\"docutils literal notranslate\">_delete_fk_sql()</code> (to pair with <code class=\"docutils literal notranslate\">_create_fk_sql()</code>)</p></li>\n<li><p><code class=\"docutils literal notranslate\">_create_check_sql()</code> and <code class=\"docutils literal notranslate\">_delete_check_sql()</code></p></li>\n</ul>\n</li>\n<li><p>The third argument of <code class=\"docutils literal notranslate\">DatabaseWrapper.__init__()</code>,\n<code class=\"docutils literal notranslate\">allow_thread_sharing</code>, is removed.</p></li>\n</ul>\n</section>\n<section id=\"admin-actions-are-no-longer-collected-from-base-modeladmin-classes\">\n<h3>Admin actions are no longer collected from base <code class=\"docutils literal notranslate\">ModelAdmin</code> classes<a class=\"heading-anchor\" href=\"#admin-actions-are-no-longer-collected-from-base-modeladmin-classes\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>For example, in older versions of Django:</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.contrib</span> <span class=\"kn\">import</span> admin\n\n\n<span class=\"k\">class</span> <span class=\"nc\">BaseAdmin</span><span class=\"p\">(</span>admin<span class=\"o\">.</span>ModelAdmin<span class=\"p\">):</span>\n    actions <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s2\">&quot;a&quot;</span><span class=\"p\">]</span>\n\n\n<span class=\"k\">class</span> <span class=\"nc\">SubAdmin</span><span class=\"p\">(</span>BaseAdmin<span class=\"p\">):</span>\n    actions <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s2\">&quot;b&quot;</span><span class=\"p\">]</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\">SubAdmin</code> would have actions <code class=\"docutils literal notranslate\">'a'</code> and <code class=\"docutils literal notranslate\">'b'</code>.</p>\n<p>Now <code class=\"docutils literal notranslate\">actions</code> follows standard Python inheritance. To get the same result as\nbefore:</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\">SubAdmin</span><span class=\"p\">(</span>BaseAdmin<span class=\"p\">):</span>\n    actions <span class=\"o\">=</span> BaseAdmin<span class=\"o\">.</span>actions <span class=\"o\">+</span> <span class=\"p\">[</span><span class=\"s2\">&quot;b&quot;</span><span class=\"p\">]</span>\n</code></pre></div>\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 1.9 and 1.10 is dropped.</p></li>\n</ul>\n</section>\n<section id=\"transactiontestcase-serialized-data-loading\">\n<h3><code class=\"docutils literal notranslate\">TransactionTestCase</code> serialized data loading<a class=\"heading-anchor\" href=\"#transactiontestcase-serialized-data-loading\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Initial data migrations are now loaded in\n<a class=\"reference internal\" href=\"/en/dev/topics/testing/tools/#django.test.TransactionTestCase\" title=\"django.test.TransactionTestCase\"><code class=\"xref py py-class docutils literal notranslate\">TransactionTestCase</code></a> at the end of the test, after the\ndatabase flush. In older versions, this data was loaded at the beginning of the\ntest, but this prevents the <a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#cmdoption-test-keepdb\"><code class=\"xref std std-option docutils literal notranslate\">test --keepdb</code></a> option from working\nproperly (the database was empty at the end of the whole test suite). This\nchange shouldn’t have an impact on your tests unless you’ve customized\n<a class=\"reference internal\" href=\"/en/dev/topics/testing/tools/#django.test.TransactionTestCase\" title=\"django.test.TransactionTestCase\"><code class=\"xref py py-class docutils literal notranslate\">TransactionTestCase</code></a>’s internals.</p>\n</section>\n<section id=\"sqlparse-is-required-dependency\">\n<h3><code class=\"docutils literal notranslate\">sqlparse</code> is required dependency<a class=\"heading-anchor\" href=\"#sqlparse-is-required-dependency\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>To simplify a few parts of Django’s database handling, <a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/sqlparse/\">sqlparse 0.2.2+</a> is now a required dependency. It’s automatically installed along\nwith Django.</p>\n</section>\n<section id=\"cached-property-aliases\">\n<h3><code class=\"docutils literal notranslate\">cached_property</code> aliases<a class=\"heading-anchor\" href=\"#cached-property-aliases\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>In usage like:</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.utils.functional</span> <span class=\"kn\">import</span> cached_property\n\n\n<span class=\"k\">class</span> <span class=\"nc\">A</span><span class=\"p\">:</span>\n    <span class=\"nd\">@cached_property</span>\n    <span class=\"k\">def</span> <span class=\"nf\">base</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"o\">...</span>\n\n    alias <span class=\"o\">=</span> base\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\">alias</code> is not cached. Where the problem can be detected (Python 3.6 and\nlater), such usage now raises <code class=\"docutils literal notranslate\">TypeError: Cannot assign the same\ncached_property to two different names ('base' and 'alias').</code></p>\n<p>Use this instead:</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\">operator</span>\n\n\n<span class=\"k\">class</span> <span class=\"nc\">A</span><span class=\"p\">:</span>\n    <span class=\"o\">...</span>\n\n    alias <span class=\"o\">=</span> <span class=\"nb\">property</span><span class=\"p\">(</span>operator<span class=\"o\">.</span>attrgetter<span class=\"p\">(</span><span class=\"s2\">&quot;base&quot;</span><span class=\"p\">))</span>\n</code></pre></div>\n</section>\n<section id=\"permissions-for-proxy-models\">\n<h3>Permissions for proxy models<a class=\"heading-anchor\" href=\"#permissions-for-proxy-models\"><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/topics/auth/default/#proxy-models-permissions-topic\"><span class=\"std std-ref\">Permissions for proxy models</span></a> are now\ncreated using the content type of the proxy model rather than the content type\nof the concrete model. A migration will update existing permissions when you\nrun <a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\">migrate</code></a>.</p>\n<p>In the admin, the change is transparent for proxy models having the same\n<code class=\"docutils literal notranslate\">app_label</code> as their concrete model. However, in older versions, users with\npermissions for a proxy model with a <em>different</em> <code class=\"docutils literal notranslate\">app_label</code> than its\nconcrete model couldn’t access the model in the admin. That’s now fixed, but\nyou might want to audit the permissions assignments for such proxy models\n(<code class=\"docutils literal notranslate\">[add|view|change|delete]_myproxy</code>) prior to upgrading to ensure the new\naccess is appropriate.</p>\n<p>Finally, proxy model permission strings must be updated to use their own\n<code class=\"docutils literal notranslate\">app_label</code>. For example, for <code class=\"docutils literal notranslate\">app.MyProxyModel</code> inheriting from\n<code class=\"docutils literal notranslate\">other_app.ConcreteModel</code>, update\n<code class=\"docutils literal notranslate\">user.has_perm('other_app.add_myproxymodel')</code> to\n<code class=\"docutils literal notranslate\">user.has_perm('app.add_myproxymodel')</code>.</p>\n</section>\n<section id=\"merging-of-form-media-assets\">\n<h3>Merging of form <code class=\"docutils literal notranslate\">Media</code> assets<a class=\"heading-anchor\" href=\"#merging-of-form-media-assets\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Form <code class=\"docutils literal notranslate\">Media</code> assets are now merged using a topological sort algorithm, as the\nold pairwise merging algorithm is insufficient for some cases. CSS and\nJavaScript files which don’t include their dependencies may now be sorted\nincorrectly (where the old algorithm produced results correctly by\ncoincidence).</p>\n<p>Audit all <code class=\"docutils literal notranslate\">Media</code> classes for any missing dependencies. For example,\nwidgets depending on <code class=\"docutils literal notranslate\">django.jQuery</code> must specify\n<code class=\"docutils literal notranslate\">js=['admin/js/jquery.init.js', ...]</code> when <a class=\"reference internal\" href=\"/en/dev/topics/forms/media/#assets-as-a-static-definition\"><span class=\"std std-ref\">declaring form media assets</span></a>.</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>\n<li><p>To improve readability, the <code class=\"docutils literal notranslate\">UUIDField</code> form field now displays values with\ndashes, e.g. <code class=\"docutils literal notranslate\">550e8400-e29b-41d4-a716-446655440000</code> instead of\n<code class=\"docutils literal notranslate\">550e8400e29b41d4a716446655440000</code>.</p></li>\n<li><p>On SQLite, <code class=\"docutils literal notranslate\">PositiveIntegerField</code> and <code class=\"docutils literal notranslate\">PositiveSmallIntegerField</code> now\ninclude a check constraint to prevent negative values in the database. If you\nhave existing invalid data and run a migration that recreates a table, you’ll\nsee <code class=\"docutils literal notranslate\">CHECK constraint failed</code>.</p></li>\n<li><p>For consistency with WSGI servers, the test client now sets the\n<code class=\"docutils literal notranslate\">Content-Length</code> header to a string rather than an integer.</p></li>\n<li><p>The return value of <a class=\"reference internal\" href=\"/en/dev/ref/utils/#django.utils.text.slugify\" title=\"django.utils.text.slugify\"><code class=\"xref py py-func docutils literal notranslate\">django.utils.text.slugify()</code></a> is no longer marked as\nHTML safe.</p></li>\n<li><p>The default truncation character used by the <a class=\"reference internal\" href=\"/en/dev/ref/templates/builtins/#std-templatefilter-urlizetrunc\"><code class=\"xref std std-tfilter docutils literal notranslate\">urlizetrunc</code></a>,\n<a class=\"reference internal\" href=\"/en/dev/ref/templates/builtins/#std-templatefilter-truncatechars\"><code class=\"xref std std-tfilter docutils literal notranslate\">truncatechars</code></a>, <a class=\"reference internal\" href=\"/en/dev/ref/templates/builtins/#std-templatefilter-truncatechars_html\"><code class=\"xref std std-tfilter docutils literal notranslate\">truncatechars_html</code></a>,\n<a class=\"reference internal\" href=\"/en/dev/ref/templates/builtins/#std-templatefilter-truncatewords\"><code class=\"xref std std-tfilter docutils literal notranslate\">truncatewords</code></a>, and <a class=\"reference internal\" href=\"/en/dev/ref/templates/builtins/#std-templatefilter-truncatewords_html\"><code class=\"xref std std-tfilter docutils literal notranslate\">truncatewords_html</code></a> template filters\nis now the real ellipsis character (<code class=\"docutils literal notranslate\">…</code>) instead of 3 dots. You may have to\nadapt some test output comparisons.</p></li>\n<li><p>Support for bytestring paths in the template filesystem loader is removed.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/utils/#django.utils.http.urlsafe_base64_encode\" title=\"django.utils.http.urlsafe_base64_encode\"><code class=\"xref py py-func docutils literal notranslate\">django.utils.http.urlsafe_base64_encode()</code></a> now returns a string instead\nof a bytestring, and <a class=\"reference internal\" href=\"/en/dev/ref/utils/#django.utils.http.urlsafe_base64_decode\" title=\"django.utils.http.urlsafe_base64_decode\"><code class=\"xref py py-func docutils literal notranslate\">django.utils.http.urlsafe_base64_decode()</code></a> may no\nlonger be passed a bytestring.</p></li>\n<li><p>Support for <code class=\"docutils literal notranslate\">cx_Oracle</code> &lt; 6.0 is removed.</p></li>\n<li><p>The minimum supported version of <code class=\"docutils literal notranslate\">mysqlclient</code> is increased from 1.3.7 to\n1.3.13.</p></li>\n<li><p>The minimum supported version of SQLite is increased from 3.7.15 to 3.8.3.</p></li>\n<li><p>In an attempt to provide more semantic query data, <code class=\"docutils literal notranslate\">NullBooleanSelect</code> now\nrenders <code class=\"docutils literal notranslate\">&lt;option&gt;</code> values of <code class=\"docutils literal notranslate\">unknown</code>, <code class=\"docutils literal notranslate\">true</code>, and <code class=\"docutils literal notranslate\">false</code> instead\nof <code class=\"docutils literal notranslate\">1</code>, <code class=\"docutils literal notranslate\">2</code>, and <code class=\"docutils literal notranslate\">3</code>. For backwards compatibility, the old values are\nstill accepted as data.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/contrib/auth/#django.contrib.auth.models.Group.name\" title=\"django.contrib.auth.models.Group.name\"><code class=\"xref py py-attr docutils literal notranslate\">Group.name</code></a> <code class=\"docutils literal notranslate\">max_length</code>\nis increased from 80 to 150 characters.</p></li>\n<li><p>Tests that violate deferrable database constraints now error when run on\nSQLite 3.20+, just like on other backends that support such constraints.</p></li>\n<li><p>To catch usage mistakes, the test <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/ref/utils/#django.utils.http.urlencode\" title=\"django.utils.http.urlencode\"><code class=\"xref py py-func docutils literal notranslate\">django.utils.http.urlencode()</code></a> now raise <code class=\"docutils literal notranslate\">TypeError</code> if <code class=\"docutils literal notranslate\">None</code> is\npassed as a value to encode because <code class=\"docutils literal notranslate\">None</code> can’t be encoded in GET and POST\ndata. Either pass an empty string or omit the value.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">ping_google</code> management command now defaults to <code class=\"docutils literal notranslate\">https</code>\ninstead of <code class=\"docutils literal notranslate\">http</code> for the sitemap’s URL. If your site uses http, use the\nnew <code class=\"docutils literal notranslate\">ping_google --sitemap-uses-http</code> option. If you use the\n<code class=\"docutils literal notranslate\">django.contrib.sitemaps.ping_google</code> function, set the new\n<code class=\"docutils literal notranslate\">sitemap_uses_https</code> argument to <code class=\"docutils literal notranslate\">False</code>.</p></li>\n<li><p><a class=\"reference internal\" href=\"/en/dev/ref/django-admin/#django-admin-runserver\"><code class=\"xref std std-djadmin docutils literal notranslate\">runserver</code></a> no longer supports <code class=\"docutils literal notranslate\">pyinotify</code> (replaced by Watchman).</p></li>\n<li><p>The <a class=\"reference internal\" href=\"/en/dev/ref/models/querysets/#django.db.models.Avg\" title=\"django.db.models.Avg\"><code class=\"xref py py-class docutils literal notranslate\">Avg</code></a>, <a class=\"reference internal\" href=\"/en/dev/ref/models/querysets/#django.db.models.StdDev\" title=\"django.db.models.StdDev\"><code class=\"xref py py-class docutils literal notranslate\">StdDev</code></a>, and\n<a class=\"reference internal\" href=\"/en/dev/ref/models/querysets/#django.db.models.Variance\" title=\"django.db.models.Variance\"><code class=\"xref py py-class docutils literal notranslate\">Variance</code></a> aggregate functions now return a\n<code class=\"docutils literal notranslate\">Decimal</code> instead of a <code class=\"docutils literal notranslate\">float</code> when the input is <code class=\"docutils literal notranslate\">Decimal</code>.</p></li>\n<li><p>Tests will fail on SQLite if apps without migrations have relations to apps\nwith migrations. This has been a documented restriction since migrations were\nadded in Django 1.7, but it fails more reliably now. You’ll see tests failing\nwith errors like <code class=\"docutils literal notranslate\">no such table: &lt;app_label&gt;_&lt;model&gt;</code>. This was observed\nwith several third-party apps that had models in tests without migrations.\nYou must add migrations for such models.</p></li>\n<li><p>Providing an integer in the <code class=\"docutils literal notranslate\">key</code> argument of the <a class=\"reference internal\" href=\"/en/dev/topics/cache/#django.core.cache.cache.delete\" title=\"django.core.cache.cache.delete\"><code class=\"xref py py-meth docutils literal notranslate\">cache.delete()</code></a> or\n<a class=\"reference internal\" href=\"/en/dev/topics/cache/#django.core.cache.cache.get\" title=\"django.core.cache.cache.get\"><code class=\"xref py py-meth docutils literal notranslate\">cache.get()</code></a> now raises <a class=\"reference external\" href=\"https://docs.python.org/3/library/exceptions.html#ValueError\" title=\"(in Python v3.14)\"><code class=\"xref py py-exc docutils literal notranslate\">ValueError</code></a>.</p></li>\n<li><p>Plural equations for some languages are changed, because the latest versions\nfrom Transifex are incorporated.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>The ability to handle <code class=\"docutils literal notranslate\">.po</code> files containing different plural equations\nfor the same language was added in Django 2.2.12.</p>\n</aside>\n</li>\n</ul>\n</section>\n</section>\n<section id=\"features-deprecated-in-2-2\">\n<span id=\"deprecated-features-2-2\"></span><h2>Features deprecated in 2.2<a class=\"heading-anchor\" href=\"#features-deprecated-in-2-2\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"model-meta-ordering-will-no-longer-affect-group-by-queries\">\n<h3>Model <code class=\"docutils literal notranslate\">Meta.ordering</code> will no longer affect <code class=\"docutils literal notranslate\">GROUP BY</code> queries<a class=\"heading-anchor\" href=\"#model-meta-ordering-will-no-longer-affect-group-by-queries\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>A model’s <code class=\"docutils literal notranslate\">Meta.ordering</code> affecting <code class=\"docutils literal notranslate\">GROUP BY</code> queries (such as\n<code class=\"docutils literal notranslate\">.annotate().values()</code>) is a common source of confusion. Such queries now\nissue a deprecation warning with the advice to add an <code class=\"docutils literal notranslate\">order_by()</code> to retain\nthe current query. <code class=\"docutils literal notranslate\">Meta.ordering</code> will be ignored in such queries starting\nin Django 3.1.</p>\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 class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\">django.utils.timezone.FixedOffset</code> is deprecated in favor of\n<a class=\"reference external\" href=\"https://docs.python.org/3/library/datetime.html#datetime.timezone\" title=\"(in Python v3.14)\"><code class=\"xref py py-class docutils literal notranslate\">datetime.timezone</code></a>.</p></li>\n<li><p>The undocumented <code class=\"docutils literal notranslate\">QuerySetPaginator</code> alias of\n<code class=\"docutils literal notranslate\">django.core.paginator.Paginator</code> is deprecated.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">FloatRangeField</code> model and form fields in <code class=\"docutils literal notranslate\">django.contrib.postgres</code>\nare deprecated in favor of a new name, <code class=\"docutils literal notranslate\">DecimalRangeField</code>, to match the\nunderlying <code class=\"docutils literal notranslate\">numrange</code> data type used in the database.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">FILE_CHARSET</code> setting is deprecated. Starting with Django 3.1, files\nread from disk must be UTF-8 encoded.</p></li>\n<li><p><code class=\"docutils literal notranslate\">django.contrib.staticfiles.storage.CachedStaticFilesStorage</code> is\ndeprecated due to the intractable problems that it has. Use\n<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> or a third-party cloud storage instead.</p></li>\n<li><p><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> is now passed <code class=\"docutils literal notranslate\">request</code> as the\nfirst positional argument, if it accepts it. Support for overrides that don’t\naccept it will be removed in Django 3.1.</p></li>\n<li><p>The <code class=\"docutils literal notranslate\">SimpleTestCase.allow_database_queries</code>,\n<code class=\"docutils literal notranslate\">TransactionTestCase.multi_db</code>, and <code class=\"docutils literal notranslate\">TestCase.multi_db</code>\nattributes are deprecated in favor of <a class=\"reference internal\" href=\"/en/dev/topics/testing/tools/#django.test.SimpleTestCase.databases\" title=\"django.test.SimpleTestCase.databases\"><code class=\"xref py py-attr docutils literal notranslate\">SimpleTestCase.databases</code></a>,\n<a class=\"reference internal\" href=\"/en/dev/topics/testing/tools/#django.test.TransactionTestCase.databases\" title=\"django.test.TransactionTestCase.databases\"><code class=\"xref py py-attr docutils literal notranslate\">TransactionTestCase.databases</code></a>, and <a class=\"reference internal\" href=\"/en/dev/topics/testing/tools/#django.test.TestCase.databases\" title=\"django.test.TestCase.databases\"><code class=\"xref py py-attr docutils literal notranslate\">TestCase.databases</code></a>.\nThese new attributes allow databases dependencies to be declared in order to\nprevent unexpected queries against non-default databases to leak state\nbetween tests. The previous behavior of <code class=\"docutils literal notranslate\">allow_database_queries=True</code> and\n<code class=\"docutils literal notranslate\">multi_db=True</code> can be achieved by setting <code class=\"docutils literal notranslate\">databases='__all__'</code>.</p></li>\n</ul>\n</section>\n</section>","rootId":"django-2-2-release-notes","toc":[{"title":"Python compatibility","anchor":"python-compatibility","children":[]},{"title":"What’s new in Django 2.2","anchor":"what-s-new-in-django-2-2","children":[{"title":"Constraints","anchor":"constraints","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.staticfiles","anchor":"django-contrib-staticfiles","children":[]},{"title":"Database backends","anchor":"database-backends","children":[]},{"title":"Generic Views","anchor":"generic-views","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":"Serialization","anchor":"serialization","children":[]},{"title":"Tests","anchor":"tests","children":[]},{"title":"URLs","anchor":"urls","children":[]},{"title":"Validators","anchor":"validators","children":[]}]}]},{"title":"Backwards incompatible changes in 2.2","anchor":"backwards-incompatible-changes-in-2-2","children":[{"title":"Database backend API","anchor":"database-backend-api","children":[]},{"title":"Admin actions are no longer collected from base ModelAdmin classes","anchor":"admin-actions-are-no-longer-collected-from-base-modeladmin-classes","children":[]},{"title":"django.contrib.gis","anchor":"id1","children":[]},{"title":"TransactionTestCase serialized data loading","anchor":"transactiontestcase-serialized-data-loading","children":[]},{"title":"sqlparse is required dependency","anchor":"sqlparse-is-required-dependency","children":[]},{"title":"cached_property aliases","anchor":"cached-property-aliases","children":[]},{"title":"Permissions for proxy models","anchor":"permissions-for-proxy-models","children":[]},{"title":"Merging of form Media assets","anchor":"merging-of-form-media-assets","children":[]},{"title":"Miscellaneous","anchor":"miscellaneous","children":[]}]},{"title":"Features deprecated in 2.2","anchor":"features-deprecated-in-2-2","children":[{"title":"Model Meta.ordering will no longer affect GROUP BY queries","anchor":"model-meta-ordering-will-no-longer-affect-group-by-queries","children":[]},{"title":"Miscellaneous","anchor":"id2","children":[]}]}],"breadcrumbs":[{"docname":"releases/index","title":"Release notes","url":"/en/dev/releases/"}],"prev":{"docname":"releases/2.2.1","title":"Django 2.2.1 release notes","url":"/en/dev/releases/2.2.1/"},"next":{"docname":"releases/2.1.15","title":"Django 2.1.15 release notes","url":"/en/dev/releases/2.1.15/"},"formats":{"html":"/en/dev/releases/2.2/","markdown":"/en/dev/releases/2.2.md","json":"/en/dev/releases/2.2.json"},"source":"https://github.com/django/django/blob/main/docs/releases/2.2.txt","official":"https://docs.djangoproject.com/en/dev/releases/2.2/","inVersions":["dev","6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2"],"inLocales":["en"]}