• Language: en
  • Documentation version: development

Django 2.2 release notes - UNDER DEVELOPMENT

Expected April 2019

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 from Django 2.1 or earlier. We’ve begun the deprecation process for some features.

See the Upgrading Django to a newer version guide if you’re updating an existing project.

Django 2.2 is designated as a long-term support release. It will receive security updates for at least three years after its release. Support for the previous LTS, Django 1.11, will end in April 2020.

Python compatibility

Django 2.2 supports Python 3.5, 3.6, and 3.7. We highly recommend and only officially support the latest release of each series.

What’s new in Django 2.2


The new CheckConstraint and UniqueConstraint classes enable adding custom database constraints. Constraints are added to models using the Meta.constraints option.

Minor features




  • The new ordering argument for ArrayAgg and StringAgg determines the ordering of the aggregated elements.
  • The new BTreeIndex, HashIndex and SpGistIndex classes allow creating B-Tree, hash, and SP-GiST indexes in the database.
  • BrinIndex now has the autosummarize parameter.
  • The new search_type parameter of SearchQuery allows searching for a phrase or raw expression.




Database backends


File Storage

File Uploads


Generic Views


Management Commands

  • The new --force-color option forces colorization of the command output.
  • inspectdb now creates models for foreign tables on PostgreSQL.
  • inspectdb --include-views now creates models for materialized views on Oracle and PostgreSQL.
  • The new inspectdb --include-partitions option allows creating models for partition tables on PostgreSQL. In older versions, models are created child tables instead the parent.
  • inspectdb now introspects DurationField for Oracle and PostgreSQL.
  • On Oracle, dbshell is wrapped with rlwrap, if available. rlwrap provides a command history and editing of keyboard input.


  • The new migrate --plan option prints the list of migration operations that will be performed.
  • NoneType can now be serialized in migrations.


  • Added support for PostgreSQL operator classes (Index.opclasses).
  • Added support for partial indexes (Index.condition).
  • Added many math database functions.
  • Setting the new ignore_conflicts parameter of QuerySet.bulk_create() to True tells the database to ignore failure to insert rows that fail uniqueness constraints or other checks.
  • The new ExtractIsoYear function extracts ISO-8601 week-numbering years from DateField and DateTimeField, and the new iso_year lookup allows querying by an ISO-8601 week-numbering year.
  • The new QuerySet.bulk_update() method allows efficiently updating specific fields on multiple model instances.
  • Django no longer always starts a transaction when a single query is being performed, such as Model.save(), QuerySet.update(), and Model.delete(). This improves the performance of autocommit by reducing the number of database round trips.

Requests and Responses


  • You can now deserialize data using natural keys containing forward references by passing handle_forward_references=True to serializers.deserialize(). Additionally, loaddata handles forward references automatically.




  • The new SimpleTestCase.assertURLEqual() assertion checks for a given URL, ignoring the ordering of the query string. assertRedirects() uses the new assertion.
  • The test Client now supports automatic JSON serialization of list and tuple data when content_type='application/json'.
  • The new ORACLE_MANAGED_FILES test database setting allows using Oracle Managed Files (OMF) tablespaces.



Backwards incompatible changes in 2.2

Database backend API

This section describes changes that may be needed in third-party database backends.

  • Third-party database backends must implement support for table check constraints or set DatabaseFeatures.supports_table_check_constraints to False.
  • Third party database backends must implement support for ignoring constraints or uniqueness errors while inserting or set DatabaseFeatures.supports_ignore_conflicts to False.
  • Third party database backends must implement introspection for DurationField or set DatabaseFeatures.can_introspect_duration_field to False.
  • DatabaseFeatures.uses_savepoints now defaults to True.
  • Third party database backends must implement support for partial indexes or set DatabaseFeatures.supports_partial_indexes to False.
  • Several SchemaEditor attributes are changed:
    • sql_create_check is replaced with sql_create_constraint.
    • sql_delete_check is replaced with sql_delete_constraint.
    • sql_create_fk is replaced with sql_foreign_key_constraint, sql_constraint, and sql_create_constraint.
  • DatabaseIntrospection.table_name_converter() and column_name_converter() are removed. Third party database backends may need to instead implement DatabaseIntrospection.identifier_converter(). In that case, the constraint names that DatabaseIntrospection.get_constraints() returns must be normalized by identifier_converter().

Admin actions are no longer collected from base ModelAdmin classes

For example, in older versions of Django:

from django.contrib import admin

class BaseAdmin(admin.ModelAdmin):
    actions = ['a']

class SubAdmin(BaseAdmin):
    actions = ['b']

SubAdmin will have actions 'a' and 'b'.

Now actions follows standard Python inheritance. To get the same result as before:

class SubAdmin(BaseAdmin):
    actions = BaseAdmin.actions + ['b']


  • Support for GDAL 1.9 and 1.10 is dropped.

TransactionTestCase serialized data loading

Initial data migrations are now loaded in TransactionTestCase at the end of the test, after the database flush. In older versions, this data was loaded at the beginning of the test, but this prevents the test --keepdb option from working properly (the database was empty at the end of the whole test suite). This change shouldn’t have an impact on your tests unless you’ve customized TransactionTestCase’s internals.

sqlparse is required dependency

To simplify a few parts of Django’s database handling, sqlparse is now a required dependency. It’s automatically installed along with Django.

cached_property aliases

In usage like:

from django.utils.functional import cached_property

class A:

    def base(self):
        return ...

    alias = base

alias is not cached. Such usage now raises TypeError: Cannot assign the same cached_property to two different names ('base' and 'alias'). on Python 3.6 and later.

Use this instead:

import operator

class A:


    alias = property(operator.attrgetter('base'))


  • To improve readability, the UUIDField form field now displays values with dashes, e.g. 550e8400-e29b-41d4-a716-446655440000 instead of 550e8400e29b41d4a716446655440000.
  • On SQLite, PositiveIntegerField and PositiveSmallIntegerField now include a check constraint to prevent negative values in the database. If you have existing invalid data and run a migration that recreates a table, you’ll see CHECK constraint failed.
  • For consistency with WSGI servers, the test client now sets the Content-Length header to a string rather than an integer.
  • The return value of django.utils.text.slugify() is no longer marked as HTML safe.
  • The default truncation character used by the urlizetrunc, truncatechars, truncatechars_html, truncatewords, and truncatewords_html template filters is now the real ellipsis character () instead of 3 dots. You may have to adapt some test output comparisons.
  • Support for bytestring paths in the template filesystem loader is removed.
  • django.utils.http.urlsafe_base64_encode() now returns a string instead of a bytestring, and django.utils.http.urlsafe_base64_decode() may no longer be passed a bytestring.
  • Support for cx_Oracle < 6.0 is removed.
  • The minimum supported version of mysqlclient is increased from 1.3.7 to 1.3.13.
  • In an attempt to provide more semantic query data, NullBooleanSelect now renders <option> values of unknown, true, and false instead of 1, 2, and 3. For backwards compatibility, the old values are still accepted as data.
  • Group.name max_length is increased from 80 to 150 characters.

Features deprecated in 2.2

Model Meta.ordering will no longer affect GROUP BY queries

A model’s Meta.ordering affecting GROUP BY queries (such as .annotate().values()) is a common source of confusion. Such queries now issue a deprecation warning with the advice to add an order_by() to retain the current query. Meta.ordering will be ignored in such queries starting in Django 3.1.


  • django.utils.timezone.FixedOffset is deprecated in favor of datetime.timezone.
  • The undocumented QuerySetPaginator alias of django.core.paginator.Paginator is deprecated.
  • The FloatRangeField model and form fields in django.contrib.postgres are deprecated in favor of a new name, DecimalRangeField, to match the underlying numrange data type used in the database.
  • The FILE_CHARSET setting is deprecated. Starting with Django 3.1, files read from disk must be UTF-8 encoded.
  • django.contrib.staticfiles.storage.CachedStaticFilesStorage is deprecated due to the intractable problems that is has. Use ManifestStaticFilesStorage or a third-party cloud storage instead.
Back to Top