Django 2.2 release notes¶
April 1, 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, 3.7, 3.8 (as of 2.2.8), and 3.9 (as of 2.2.17). We highly recommend and only officially support the latest release of each series.
What’s new in Django 2.2¶
Constraints¶
The new CheckConstraint and
UniqueConstraint classes enable adding custom
database constraints. Constraints are added to models using the
Meta.constraints option.
Minor features¶
django.contrib.admin¶
- Added a CSS class to the column headers of
TabularInline.
django.contrib.auth¶
- The
HttpRequestis now passed as the first positional argument toRemoteUserBackend.configure_user(), if it accepts it.
django.contrib.postgres¶
- The new
orderingargument forArrayAggandStringAggdetermines the ordering of the aggregated elements. - The new
BTreeIndex,HashIndexandSpGistIndexclasses allow creatingB-Tree,hash, andSP-GiSTindexes in the database. BrinIndexnow has theautosummarizeparameter.- The new
search_typeparameter ofSearchQueryallows searching for a phrase or raw expression.
django.contrib.staticfiles¶
- Added path matching to the
collectstatic --ignoreoption so that patterns like/vendor/*.jscan be used.
Database backends¶
- Added result streaming for
QuerySet.iterator()on SQLite.
Generic Views¶
- The new
View.setuphook initializes view attributes before callingdispatch(). It allows mixins to setup instance attributes for reuse in child classes.
Internationalization¶
- Added support and translations for the Armenian language.
Management Commands¶
- The new
--force-coloroption forces colorization of the command output. inspectdbnow creates models for foreign tables on PostgreSQL.inspectdb --include-viewsnow creates models for materialized views on Oracle and PostgreSQL.- The new
inspectdb --include-partitionsoption allows creating models for partition tables on PostgreSQL. In older versions, models are created child tables instead the parent. inspectdbnow introspectsDurationFieldfor Oracle and PostgreSQL, andAutoFieldfor SQLite.- On Oracle,
dbshellis wrapped withrlwrap, if available.rlwrapprovides a command history and editing of keyboard input. - The new
makemigrations --no-headeroption avoids writing header comments in generated migration file(s). This option is also available forsquashmigrations. runservercan now use Watchman to improve the performance of watching a large number of files for changes.
Migrations¶
- The new
migrate --planoption prints the list of migration operations that will be performed. NoneTypecan now be serialized in migrations.- You can now register custom serializers for migrations.
Models¶
- Added support for PostgreSQL operator classes (
Index.opclasses). - Added support for partial indexes (
Index.condition). - Added the
NullIfandReversedatabase functions, as well as many math database functions. - Setting the new
ignore_conflictsparameter ofQuerySet.bulk_create()toTruetells the database to ignore failure to insert rows that fail uniqueness constraints or other checks. - The new
ExtractIsoYearfunction extracts ISO-8601 week-numbering years fromDateFieldandDateTimeField, and the newiso_yearlookup 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(), andModel.delete(). This improves the performance of autocommit by reducing the number of database round trips. - Added SQLite support for the
StdDevandVariancefunctions. - The handling of
DISTINCTaggregation is added to theAggregateclass. Addingallow_distinct = Trueas a class attribute onAggregatesubclasses allows adistinctkeyword argument to be specified on initialization to ensure that the aggregate function is only called for each distinct value ofexpressions. - The
RelatedManager.add(),create(),remove(),set(),get_or_create(), andupdate_or_create()methods are now allowed on many-to-many relationships with intermediate models. The newthrough_defaultsargument is used to specify values for new intermediate model instance(s).
Requests and Responses¶
- Added
HttpRequest.headersto allow simple access to a request’s headers.
Serialization¶
- You can now deserialize data using natural keys containing forward
references by passing
handle_forward_references=Truetoserializers.deserialize(). Additionally,loaddatahandles forward references automatically.
Tests¶
- The new
SimpleTestCase.assertURLEqual()assertion checks for a given URL, ignoring the ordering of the query string.assertRedirects()uses the new assertion. - The test
Clientnow supports automatic JSON serialization of list and tupledatawhencontent_type='application/json'. - The new
ORACLE_MANAGED_FILEStest database setting allows using Oracle Managed Files (OMF) tablespaces. - Deferrable database constraints are now checked at the end of each
TestCasetest on SQLite 3.20+, just like on other backends that support deferrable constraints. These checks aren’t implemented for older versions of SQLite because they would require expensive table introspection there. DiscoverRunnernow skips the setup of databases not referenced by tests.
URLs¶
- The new
ResolverMatch.routeattribute stores the route of the matching URL pattern.
Validators¶
MaxValueValidator,MinValueValidator,MinLengthValidator, andMaxLengthValidatornow accept a callablelimit_value.
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_constraintstoFalse. - Third party database backends must implement support for ignoring
constraints or uniqueness errors while inserting or set
DatabaseFeatures.supports_ignore_conflictstoFalse. - Third party database backends must implement introspection for
DurationFieldor setDatabaseFeatures.can_introspect_duration_fieldtoFalse. DatabaseFeatures.uses_savepointsnow defaults toTrue.- Third party database backends must implement support for partial indexes or
set
DatabaseFeatures.supports_partial_indexestoFalse. DatabaseIntrospection.table_name_converter()andcolumn_name_converter()are removed. Third party database backends may need to instead implementDatabaseIntrospection.identifier_converter(). In that case, the constraint names thatDatabaseIntrospection.get_constraints()returns must be normalized byidentifier_converter().- SQL generation for indexes is moved from
IndextoSchemaEditorand theseSchemaEditormethods are added:_create_primary_key_sql()and_delete_primary_key_sql()_delete_index_sql()(to pair with_create_index_sql())_delete_unique_sql(to pair with_create_unique_sql())_delete_fk_sql()(to pair with_create_fk_sql())_create_check_sql()and_delete_check_sql()
- The third argument of
DatabaseWrapper.__init__(),allow_thread_sharing, is removed.
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 would 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']
django.contrib.gis¶
- 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 0.2.2+ 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:
@cached_property
def base(self):
return ...
alias = base
alias is not cached. Where the problem can be detected (Python 3.6 and
later), such usage now raises TypeError: Cannot assign the same
cached_property to two different names ('base' and 'alias').
Use this instead:
import operator
class A:
...
alias = property(operator.attrgetter('base'))
Permissions for proxy models¶
Permissions for proxy models are now
created using the content type of the proxy model rather than the content type
of the concrete model. A migration will update existing permissions when you
run migrate.
In the admin, the change is transparent for proxy models having the same
app_label as their concrete model. However, in older versions, users with
permissions for a proxy model with a different app_label than its
concrete model couldn’t access the model in the admin. That’s now fixed, but
you might want to audit the permissions assignments for such proxy models
([add|view|change|delete]_myproxy) prior to upgrading to ensure the new
access is appropriate.
Finally, proxy model permission strings must be updated to use their own
app_label. For example, for app.MyProxyModel inheriting from
other_app.ConcreteModel, update
user.has_perm('other_app.add_myproxymodel') to
user.has_perm('app.add_myproxymodel').
Merging of form Media assets¶
Form Media assets are now merged using a topological sort algorithm, as the
old pairwise merging algorithm is insufficient for some cases. CSS and
JavaScript files which don’t include their dependencies may now be sorted
incorrectly (where the old algorithm produced results correctly by
coincidence).
Audit all Media classes for any missing dependencies. For example,
widgets depending on django.jQuery must specify
js=['admin/js/jquery.init.js', ...] when declaring form media assets.
Miscellaneous¶
To improve readability, the
UUIDFieldform field now displays values with dashes, e.g.550e8400-e29b-41d4-a716-446655440000instead of550e8400e29b41d4a716446655440000.On SQLite,
PositiveIntegerFieldandPositiveSmallIntegerFieldnow 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 seeCHECK constraint failed.For consistency with WSGI servers, the test client now sets the
Content-Lengthheader 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, andtruncatewords_htmltemplate 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, anddjango.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
mysqlclientis increased from 1.3.7 to 1.3.13.The minimum supported version of SQLite is increased from 3.7.15 to 3.8.3.
In an attempt to provide more semantic query data,
NullBooleanSelectnow renders<option>values ofunknown,true, andfalseinstead of1,2, and3. For backwards compatibility, the old values are still accepted as data.Group.namemax_lengthis increased from 80 to 150 characters.Tests that violate deferrable database constraints now error when run on SQLite 3.20+, just like on other backends that support such constraints.
To catch usage mistakes, the test
Clientanddjango.utils.http.urlencode()now raiseTypeErrorifNoneis passed as a value to encode becauseNonecan’t be encoded in GET and POST data. Either pass an empty string or omit the value.The
ping_googlemanagement command now defaults tohttpsinstead ofhttpfor the sitemap’s URL. If your site uses http, use the newping_google --sitemap-uses-httpoption. If you use theping_google()function, set the newsitemap_uses_httpsargument toFalse.runserverno longer supportspyinotify(replaced by Watchman).The
Avg,StdDev, andVarianceaggregate functions now return aDecimalinstead of afloatwhen the input isDecimal.Tests will fail on SQLite if apps without migrations have relations to apps with migrations. This has been a documented restriction since migrations were added in Django 1.7, but it fails more reliably now. You’ll see tests failing with errors like
no such table: <app_label>_<model>. This was observed with several third-party apps that had models in tests without migrations. You must add migrations for such models.Providing an integer in the
keyargument of thecache.delete()orcache.get()now raisesValueError.Plural equations for some languages are changed, because the latest versions from Transifex are incorporated.
Note
The ability to handle
.pofiles containing different plural equations for the same language was added in Django 2.2.12.
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.
Miscellaneous¶
django.utils.timezone.FixedOffsetis deprecated in favor ofdatetime.timezone.- The undocumented
QuerySetPaginatoralias ofdjango.core.paginator.Paginatoris deprecated. - The
FloatRangeFieldmodel and form fields indjango.contrib.postgresare deprecated in favor of a new name,DecimalRangeField, to match the underlyingnumrangedata type used in the database. - The
FILE_CHARSETsetting is deprecated. Starting with Django 3.1, files read from disk must be UTF-8 encoded. django.contrib.staticfiles.storage.CachedStaticFilesStorageis deprecated due to the intractable problems that it has. UseManifestStaticFilesStorageor a third-party cloud storage instead.RemoteUserBackend.configure_user()is now passedrequestas the first positional argument, if it accepts it. Support for overrides that don’t accept it will be removed in Django 3.1.- The
SimpleTestCase.allow_database_queries,TransactionTestCase.multi_db, andTestCase.multi_dbattributes are deprecated in favor ofSimpleTestCase.databases,TransactionTestCase.databases, andTestCase.databases. These new attributes allow databases dependencies to be declared in order to prevent unexpected queries against non-default databases to leak state between tests. The previous behavior ofallow_database_queries=Trueandmulti_db=Truecan be achieved by settingdatabases='__all__'.