========================Django 4.0 release notes========================*December 7, 2021*Welcome to Django 4.0!These release notes cover the :ref:`new features <whats-new-4.0>`, as well assome :ref:`backwards incompatible changes <backwards-incompatible-4.0>` you'llwant to be aware of when upgrading from Django 3.2 or earlier. We've:ref:`begun the deprecation process for some features<deprecated-features-4.0>`.See the :doc:`/howto/upgrade-version` guide if you're updating an existingproject.Python compatibility====================Django 4.0 supports Python 3.8, 3.9, and 3.10. We **highly recommend** and onlyofficially support the latest release of each series.The Django 3.2.x series is the last to support Python 3.6 and 3.7... _whats-new-4.0:What's new in Django 4.0========================``zoneinfo`` default timezone implementation--------------------------------------------The Python standard library's :mod:`zoneinfo` is now the default timezoneimplementation in Django.This is the next step in the migration from using ``pytz`` to using:mod:`zoneinfo`. Django 3.2 allowed the use of non-``pytz`` time zones. Django4.0 makes ``zoneinfo`` the default implementation. Support for ``pytz`` is nowdeprecated and will be removed in Django 5.0.:mod:`zoneinfo` is part of the Python standard library from Python 3.9. The``backports.zoneinfo`` package is automatically installed alongside Django ifyou are using Python 3.8.The move to ``zoneinfo`` should be largely transparent. Selection of thecurrent timezone, conversion of datetime instances to the current timezone informs and templates, as well as operations on aware datetimes in UTC areunaffected.However, if you are working with non-UTC time zones, and using the ``pytz````normalize()`` and ``localize()`` APIs, possibly with the :setting:`TIME_ZONE<DATABASE-TIME_ZONE>` setting, you will need to audit your code, since ``pytz``and ``zoneinfo`` are not entirely equivalent.To give time for such an audit, the transitional :setting:`USE_DEPRECATED_PYTZ`setting allows continued use of ``pytz`` during the 4.x release cycle. Thissetting will be removed in Django 5.0.In addition, a `pytz_deprecation_shim`_ package, created by the ``zoneinfo``author, can be used to assist with the migration from ``pytz``. This packageprovides shims to help you safely remove ``pytz``, and has a detailed`migration guide`_ showing how to move to the new ``zoneinfo`` APIs.Using `pytz_deprecation_shim`_ and the :setting:`USE_DEPRECATED_PYTZ`transitional setting is recommended if you need a gradual update path... _pytz_deprecation_shim: https://pytz-deprecation-shim.readthedocs.io/en/latest/index.html.. _migration guide: https://pytz-deprecation-shim.readthedocs.io/en/latest/migration.htmlFunctional unique constraints-----------------------------The new :attr:`*expressions <django.db.models.UniqueConstraint.expressions>`positional argument of:class:`UniqueConstraint() <django.db.models.UniqueConstraint>` enablescreating functional unique constraints on expressions and database functions.For example::from django.db import modelsfrom django.db.models import UniqueConstraintfrom django.db.models.functions import Lowerclass MyModel(models.Model):first_name = models.CharField(max_length=255)last_name = models.CharField(max_length=255)class Meta:constraints = [UniqueConstraint(Lower('first_name'),Lower('last_name').desc(),name='first_last_name_unique',),]Functional unique constraints are added to models using the:attr:`Meta.constraints <django.db.models.Options.constraints>` option.``scrypt`` password hasher--------------------------The new :ref:`scrypt password hasher <scrypt-usage>` is more secure andrecommended over PBKDF2. However, it's not the default as it requires OpenSSL1.1+ and more memory.Redis cache backend-------------------The new ``django.core.cache.backends.redis.RedisCache`` cache backend providesbuilt-in support for caching with Redis. `redis-py`_ 3.0.0 or higher isrequired. For more details, see the :ref:`documentation on caching with Redisin Django <redis>`... _`redis-py`: https://pypi.org/project/redis/Template based form rendering-----------------------------:class:`Forms <django.forms.Form>`, :doc:`Formsets </topics/forms/formsets>`,and :class:`~django.forms.ErrorList` are now rendered using the template engineto enhance customization. See the new :meth:`~django.forms.Form.render`,:meth:`~django.forms.Form.get_context`, and:attr:`~django.forms.Form.template_name` for ``Form`` and:ref:`formset rendering <formset-rendering>` for ``Formset``.Minor features--------------:mod:`django.contrib.admin`~~~~~~~~~~~~~~~~~~~~~~~~~~~* The ``admin/base.html`` template now has a new block ``header`` whichcontains the admin site header.* The new :meth:`.ModelAdmin.get_formset_kwargs` method allows customizing thekeyword arguments passed to the constructor of a formset.* The navigation sidebar now has a quick filter toolbar.* The new context variable ``model`` which contains the model class for eachmodel is added to the :meth:`.AdminSite.each_context` method.* The new :attr:`.ModelAdmin.search_help_text` attribute allows specifying adescriptive text for the search box.* The :attr:`.InlineModelAdmin.verbose_name_plural` attribute now fallbacks tothe :attr:`.InlineModelAdmin.verbose_name` + ``'s'``.* jQuery is upgraded from version 3.5.1 to 3.6.0.:mod:`django.contrib.admindocs`~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~* The admindocs now allows esoteric setups where :setting:`ROOT_URLCONF` is nota string.* The model section of the ``admindocs`` now shows cached properties.:mod:`django.contrib.auth`~~~~~~~~~~~~~~~~~~~~~~~~~~* The default iteration count for the PBKDF2 password hasher is increased from260,000 to 320,000.* The new:attr:`LoginView.next_page <django.contrib.auth.views.LoginView.next_page>`attribute and:meth:`~django.contrib.auth.views.LoginView.get_default_redirect_url` methodallow customizing the redirect after login.:mod:`django.contrib.gis`~~~~~~~~~~~~~~~~~~~~~~~~~* Added support for SpatiaLite 5.* :class:`~django.contrib.gis.gdal.GDALRaster` now allows creating rasters inany GDAL virtual filesystem.* The new :class:`~django.contrib.gis.admin.GISModelAdmin` class allowscustomizing the widget used for ``GeometryField``. This is encouraged insteadof deprecated ``GeoModelAdmin`` and ``OSMGeoAdmin``.:mod:`django.contrib.postgres`~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~* The PostgreSQL backend now supports connecting by a service name. See:ref:`postgresql-connection-settings` for more details.* The new :class:`~django.contrib.postgres.operations.AddConstraintNotValid`operation allows creating check constraints on PostgreSQL without verifyingthat all existing rows satisfy the new constraint.* The new :class:`~django.contrib.postgres.operations.ValidateConstraint`operation allows validating check constraints which were created using:class:`~django.contrib.postgres.operations.AddConstraintNotValid` onPostgreSQL.* The new:class:`ArraySubquery() <django.contrib.postgres.expressions.ArraySubquery>`expression allows using subqueries to construct lists of values onPostgreSQL.* The new :lookup:`trigram_word_similar` lookup, and the:class:`TrigramWordDistance()<django.contrib.postgres.search.TrigramWordDistance>` and:class:`TrigramWordSimilarity()<django.contrib.postgres.search.TrigramWordSimilarity>` expressions allowusing trigram word similarity.:mod:`django.contrib.staticfiles`~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~* :class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage` nowreplaces paths to JavaScript source map references with their hashedcounterparts.* The new ``manifest_storage`` argument of:class:`~django.contrib.staticfiles.storage.ManifestFilesMixin` and:class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage`allows customizing the manifest file storage.Cache~~~~~* The new async API for ``django.core.cache.backends.base.BaseCache`` beginsthe process of making cache backends async-compatible. The new async methodsall have ``a`` prefixed names, e.g. ``aadd()``, ``aget()``, ``aset()``,``aget_or_set()``, or ``adelete_many()``.Going forward, the ``a`` prefix will be used for async variants of methodsgenerally.CSRF~~~~* CSRF protection now consults the ``Origin`` header, if present. To facilitatethis, :ref:`some changes <csrf-trusted-origins-changes-4.0>` to the:setting:`CSRF_TRUSTED_ORIGINS` setting are required.Forms~~~~~* :class:`~django.forms.ModelChoiceField` now includes the provided value inthe ``params`` argument of a raised:exc:`~django.core.exceptions.ValidationError` for the ``invalid_choice``error message. This allows custom error messages to use the ``%(value)s``placeholder.* :class:`~django.forms.formsets.BaseFormSet` now renders non-form errors withan additional class of ``nonform`` to help distinguish them fromform-specific errors.* :class:`~django.forms.formsets.BaseFormSet` now allows customizing the widgetused when deleting forms via:attr:`~django.forms.formsets.BaseFormSet.can_delete` by setting the:attr:`~django.forms.formsets.BaseFormSet.deletion_widget` attribute oroverriding :meth:`~django.forms.formsets.BaseFormSet.get_deletion_widget`method.Internationalization~~~~~~~~~~~~~~~~~~~~* Added support and translations for the Malay language.Generic Views~~~~~~~~~~~~~* :class:`~django.views.generic.edit.DeleteView` now uses:class:`~django.views.generic.edit.FormMixin`, allowing you to provide a:class:`~django.forms.Form` subclass, with a checkbox for example, to confirmdeletion. In addition, this allows ``DeleteView`` to function with:class:`django.contrib.messages.views.SuccessMessageMixin`.In accordance with ``FormMixin``, object deletion for POST requests ishandled in ``form_valid()``. Custom delete logic in ``delete()`` handlersshould be moved to ``form_valid()``, or a shared helper method, as needed.Logging~~~~~~~* The alias of the database used in an SQL call is now passed as extra contextalong with each message to the :ref:`django-db-logger` logger.Management Commands~~~~~~~~~~~~~~~~~~~* The :djadmin:`runserver` management command now supports the:option:`--skip-checks` option.* On PostgreSQL, :djadmin:`dbshell` now supports specifying a password file.* The :djadmin:`shell` command now respects :py:data:`sys.__interactivehook__`at startup. This allows loading shell history between interactive sessions.As a consequence, ``readline`` is no longer loaded if running in *isolated*mode.* The new :attr:`BaseCommand.suppressed_base_arguments<django.core.management.BaseCommand.suppressed_base_arguments>` attributeallows suppressing unsupported default command options in the help output.* The new :option:`startapp --exclude` and :option:`startproject --exclude`options allow excluding directories from the template.Models~~~~~~* New :meth:`QuerySet.contains(obj) <.QuerySet.contains>` method returnswhether the queryset contains the given object. This tries to perform thequery in the simplest and fastest way possible.* The new ``precision`` argument of the:class:`Round() <django.db.models.functions.Round>` database function allowsspecifying the number of decimal places after rounding.* :meth:`.QuerySet.bulk_create` now sets the primary key on objects when usingSQLite 3.35+.* :class:`~django.db.models.DurationField` now supports multiplying anddividing by scalar values on SQLite.* :meth:`.QuerySet.bulk_update` now returns the number of objects updated.* The new :attr:`.Expression.empty_result_set_value` attribute allowsspecifying a value to return when the function is used over an empty resultset.* The ``skip_locked`` argument of :meth:`.QuerySet.select_for_update()` is nowallowed on MariaDB 10.6+.* :class:`~django.db.models.Lookup` expressions may now be used in ``QuerySet``annotations, aggregations, and directly in filters.* The new :ref:`default <aggregate-default>` argument for built-in aggregatesallows specifying a value to be returned when the queryset (or grouping)contains no entries, rather than ``None``.Requests and Responses~~~~~~~~~~~~~~~~~~~~~~* The :class:`~django.middleware.security.SecurityMiddleware` now adds the:ref:`Cross-Origin Opener Policy <cross-origin-opener-policy>` header with avalue of ``'same-origin'`` to prevent cross-origin popups from sharing thesame browsing context. You can prevent this header from being added bysetting the :setting:`SECURE_CROSS_ORIGIN_OPENER_POLICY` setting to ``None``.Signals~~~~~~~* The new ``stdout`` argument for :func:`~django.db.models.signals.pre_migrate`and :func:`~django.db.models.signals.post_migrate` signals allows redirectingoutput to a stream-like object. It should be preferred over:py:data:`sys.stdout` and :py:func:`print` when emitting verbose output inorder to allow proper capture when testing.Templates~~~~~~~~~* :tfilter:`floatformat` template filter now allows using the ``u`` suffix toforce disabling localization.Tests~~~~~* The new ``serialized_aliases`` argument of:func:`django.test.utils.setup_databases` determines which:setting:`DATABASES` aliases test databases should have their stateserialized to allow usage of the:ref:`serialized_rollback <test-case-serialized-rollback>` feature.* Django test runner now supports a :option:`--buffer <test --buffer>` optionwith parallel tests.* The new ``logger`` argument to :class:`~django.test.runner.DiscoverRunner`allows a Python :py:ref:`logger <logger>` to be used for logging.* The new :meth:`.DiscoverRunner.log` method provides a way to log messagesthat uses the ``DiscoverRunner.logger``, or prints to the console if not set.* Django test runner now supports a :option:`--shuffle <test --shuffle>` optionto execute tests in a random order.* The :option:`test --parallel` option now supports the value ``auto`` to runone test process for each processor core.* :meth:`.TestCase.captureOnCommitCallbacks` now captures new callbacks addedwhile executing :func:`.transaction.on_commit` callbacks... _backwards-incompatible-4.0:Backwards incompatible changes in 4.0=====================================Database backend API--------------------This section describes changes that may be needed in third-party databasebackends.* ``DatabaseOperations.year_lookup_bounds_for_date_field()`` and``year_lookup_bounds_for_datetime_field()`` methods now take the optional``iso_year`` argument in order to support bounds for ISO-8601 week-numberingyears.* The second argument of ``DatabaseSchemaEditor._unique_sql()`` and``_create_unique_sql()`` methods is now ``fields`` instead of ``columns``.:mod:`django.contrib.gis`-------------------------* Support for PostGIS 2.3 is removed.* Support for GDAL 2.0 and GEOS 3.5 is removed.Dropped support for PostgreSQL 9.6----------------------------------Upstream support for PostgreSQL 9.6 ends in November 2021. Django 4.0 supportsPostgreSQL 10 and higher.Also, the minimum supported version of ``psycopg2`` is increased from 2.5.4 to2.8.4, as ``psycopg2`` 2.8.4 is the first release to support Python 3.8.Dropped support for Oracle 12.2 and 18c---------------------------------------Upstream support for Oracle 12.2 ends in March 2022 and for Oracle 18c it endsin June 2021. Django 3.2 will be supported until April 2024. Django 4.0officially supports Oracle 19c... _csrf-trusted-origins-changes-4.0:``CSRF_TRUSTED_ORIGINS`` changes--------------------------------Format change~~~~~~~~~~~~~Values in the :setting:`CSRF_TRUSTED_ORIGINS` setting must include the scheme(e.g. ``'http://'`` or ``'https://'``) instead of only the hostname.Also, values that started with a dot, must now also include an asterisk beforethe dot. For example, change ``'.example.com'`` to ``'https://*.example.com'``.A system check detects any required changes.Configuring it may now be required~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~As CSRF protection now consults the ``Origin`` header, you may need to set:setting:`CSRF_TRUSTED_ORIGINS`, particularly if you allow requests fromsubdomains by setting :setting:`CSRF_COOKIE_DOMAIN` (or:setting:`SESSION_COOKIE_DOMAIN` if :setting:`CSRF_USE_SESSIONS` is enabled) toa value starting with a dot.``SecurityMiddleware`` no longer sets the ``X-XSS-Protection`` header---------------------------------------------------------------------The :class:`~django.middleware.security.SecurityMiddleware` no longer sets the``X-XSS-Protection`` header if the ``SECURE_BROWSER_XSS_FILTER`` setting is``True``. The setting is removed.Most modern browsers don't honor the ``X-XSS-Protection`` HTTP header. You canuse Content-Security-Policy_ without allowing ``'unsafe-inline'`` scriptsinstead.If you want to support legacy browsers and set the header, use this line in acustom middleware::response.headers.setdefault('X-XSS-Protection', '1; mode=block').. _Content-Security-Policy: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-PolicyMigrations autodetector changes-------------------------------The migrations autodetector now uses model states instead of model classes.Also, migration operations for ``ForeignKey`` and ``ManyToManyField`` fields nolonger specify attributes which were not passed to the fields duringinitialization.As a side-effect, running ``makemigrations`` might generate no-op``AlterField`` operations for ``ManyToManyField`` and ``ForeignKey`` fields insome cases.``DeleteView`` changes----------------------:class:`~django.views.generic.edit.DeleteView` now uses:class:`~django.views.generic.edit.FormMixin` to handle POST requests. As aconsequence, any custom deletion logic in ``delete()`` handlers should bemoved to ``form_valid()``, or a shared helper method, if required.Table and column naming scheme changes on Oracle------------------------------------------------Django 4.0 inadvertently changed the table and column naming scheme on Oracle.This causes errors for models and fields with names longer than 30 characters.Unfortunately, renaming some Oracle tables and columns is required. Use theupgrade script in :ticket:`33789 <33789#comment:15>` to generate ``RENAME``statements to change naming scheme.Miscellaneous-------------* Support for ``cx_Oracle`` < 7.0 is removed.* To allow serving a Django site on a subpath without changing the value of:setting:`STATIC_URL`, the leading slash is removed from that setting (now``'static/'``) in the default :djadmin:`startproject` template.* The :class:`~django.contrib.admin.AdminSite` method for the admin ``index``view is no longer decorated with ``never_cache`` when accessed directly,rather than via the recommended ``AdminSite.urls`` property, or``AdminSite.get_urls()`` method.* Unsupported operations on a sliced queryset now raise ``TypeError`` insteadof ``AssertionError``.* The undocumented ``django.test.runner.reorder_suite()`` function is renamedto ``reorder_tests()``. It now accepts an iterable of tests rather than atest suite, and returns an iterator of tests.* Calling ``FileSystemStorage.delete()`` with an empty ``name`` now raises``ValueError`` instead of ``AssertionError``.* Calling ``EmailMultiAlternatives.attach_alternative()`` or``EmailMessage.attach()`` with an invalid ``content`` or ``mimetype``arguments now raise ``ValueError`` instead of ``AssertionError``.* :meth:`~django.test.SimpleTestCase.assertHTMLEqual` no longer considers anon-boolean attribute without a value equal to an attribute with the samename and value.* Tests that fail to load, for example due to syntax errors, now always matchwhen using :option:`test --tag`.* The undocumented ``django.contrib.admin.utils.lookup_needs_distinct()``function is renamed to ``lookup_spawns_duplicates()``.* The undocumented ``HttpRequest.get_raw_uri()`` method is removed. The:meth:`.HttpRequest.build_absolute_uri` method may be a suitable alternative.* The ``object`` argument of undocumented ``ModelAdmin.log_addition()``,``log_change()``, and ``log_deletion()`` methods is renamed to ``obj``.* :class:`~django.utils.feedgenerator.RssFeed`,:class:`~django.utils.feedgenerator.Atom1Feed`, and their subclasses now emitelements with no content as self-closing tags.* ``NodeList.render()`` no longer casts the output of ``render()`` method forindividual nodes to a string. ``Node.render()`` should always return a stringas documented.* The ``where_class`` property of ``django.db.models.sql.query.Query`` and the``where_class`` argument to the private ``get_extra_restriction()`` method of``ForeignObject`` and ``ForeignObjectRel`` are removed. If needed, initialize``django.db.models.sql.where.WhereNode`` instead.* The ``filter_clause`` argument of the undocumented ``Query.add_filter()``method is replaced by two positional arguments ``filter_lhs`` and``filter_rhs``.* :class:`~django.middleware.csrf.CsrfViewMiddleware` now uses``request.META['CSRF_COOKIE_NEEDS_UPDATE']`` in place of``request.META['CSRF_COOKIE_USED']``, ``request.csrf_cookie_needs_reset``,and ``response.csrf_cookie_set`` to track whether the CSRF cookie should besent. This is an undocumented, private API.* The undocumented ``TRANSLATOR_COMMENT_MARK`` constant is moved from``django.template.base`` to ``django.utils.translation.template``.* The ``real_apps`` argument of the undocumented``django.db.migrations.state.ProjectState.__init__()`` method must now be aset if provided.* :class:`~django.forms.RadioSelect` and:class:`~django.forms.CheckboxSelectMultiple` widgets are now rendered in``<div>`` tags so they are announced more concisely by screen readers. If youneed the previous behavior, :ref:`override the widget template<overriding-built-in-widget-templates>` with the appropriate template fromDjango 3.2.* The :tfilter:`floatformat` template filter no longer depends on the``USE_L10N`` setting and always returns localized output. Use the ``u``suffix to disable localization.* The default value of the ``USE_L10N`` setting is changed to ``True``. See the:ref:`Localization section <use_l10n_deprecation>` above for more details.* As part of the :ref:`move to zoneinfo <whats-new-4.0>`,:attr:`django.utils.timezone.utc` is changed to alias:attr:`datetime.timezone.utc`.* The minimum supported version of ``asgiref`` is increased from 3.3.2 to3.4.1... _deprecated-features-4.0:Features deprecated in 4.0==========================Use of ``pytz`` time zones--------------------------As part of the :ref:`move to zoneinfo <whats-new-4.0>`, use of ``pytz`` timezones is deprecated.Accordingly, the ``is_dst`` arguments to the following are also deprecated:* :meth:`django.db.models.query.QuerySet.datetimes`* :func:`django.db.models.functions.Trunc`* :func:`django.db.models.functions.TruncSecond`* :func:`django.db.models.functions.TruncMinute`* :func:`django.db.models.functions.TruncHour`* :func:`django.db.models.functions.TruncDay`* :func:`django.db.models.functions.TruncWeek`* :func:`django.db.models.functions.TruncMonth`* :func:`django.db.models.functions.TruncQuarter`* :func:`django.db.models.functions.TruncYear`* :func:`django.utils.timezone.make_aware`Support for use of ``pytz`` will be removed in Django 5.0.Time zone support-----------------In order to follow good practice, the default value of the :setting:`USE_TZ`setting will change from ``False`` to ``True``, and time zone support will beenabled by default, in Django 5.0.Note that the default :file:`settings.py` file created by:djadmin:`django-admin startproject <startproject>` includes:setting:`USE_TZ = True <USE_TZ>` since Django 1.4.You can set ``USE_TZ`` to ``False`` in your project settings before then toopt-out... _use_l10n_deprecation:Localization------------In order to follow good practice, the default value of the ``USE_L10N`` settingis changed from ``False`` to ``True``.Moreover ``USE_L10N`` is deprecated as of this release. Starting with Django5.0, by default, any date or number displayed by Django will be localized.The :ttag:`{% localize %} <localize>` tag and the :tfilter:`localize`/:tfilter:`unlocalize` filters will still be honored by Django.Miscellaneous-------------* ``SERIALIZE`` test setting is deprecated as it can be inferred from the:attr:`~django.test.TestCase.databases` with the:ref:`serialized_rollback <test-case-serialized-rollback>` option enabled.* The undocumented ``django.utils.baseconv`` module is deprecated.* The undocumented ``django.utils.datetime_safe`` module is deprecated.* The default sitemap protocol for sitemaps built outside the context of arequest will change from ``'http'`` to ``'https'`` in Django 5.0.* The ``extra_tests`` argument for :meth:`.DiscoverRunner.build_suite` and:meth:`.DiscoverRunner.run_tests` is deprecated.* The :class:`~django.contrib.postgres.aggregates.ArrayAgg`,:class:`~django.contrib.postgres.aggregates.JSONBAgg`, and:class:`~django.contrib.postgres.aggregates.StringAgg` aggregates will return``None`` when there are no rows instead of ``[]``, ``[]``, and ``''``respectively in Django 5.0. If you need the previous behavior, explicitly set``default`` to ``Value([])``, ``Value('[]')``, or ``Value('')``.* The ``django.contrib.gis.admin.GeoModelAdmin`` and ``OSMGeoAdmin`` classesare deprecated. Use :class:`~django.contrib.admin.ModelAdmin` and:class:`~django.contrib.gis.admin.GISModelAdmin` instead.* Since form rendering now uses the template engine, the undocumented``BaseForm._html_output()`` helper method is deprecated.* The ability to return a ``str`` from ``ErrorList`` and ``ErrorDict`` isdeprecated. It is expected these methods return a ``SafeString``.Features removed in 4.0=======================These features have reached the end of their deprecation cycle and are removedin Django 4.0.See :ref:`deprecated-features-3.0` for details on these changes, including howto remove usage of these features.* ``django.utils.http.urlquote()``, ``urlquote_plus()``, ``urlunquote()``, and``urlunquote_plus()`` are removed.* ``django.utils.encoding.force_text()`` and ``smart_text()`` are removed.* ``django.utils.translation.ugettext()``, ``ugettext_lazy()``,``ugettext_noop()``, ``ungettext()``, and ``ungettext_lazy()`` are removed.* ``django.views.i18n.set_language()`` doesn't set the user language in``request.session`` (key ``_language``).* ``alias=None`` is required in the signature of``django.db.models.Expression.get_group_by_cols()`` subclasses.* ``django.utils.text.unescape_entities()`` is removed.* ``django.utils.http.is_safe_url()`` is removed.See :ref:`deprecated-features-3.1` for details on these changes, including howto remove usage of these features.* The ``PASSWORD_RESET_TIMEOUT_DAYS`` setting is removed.* The :lookup:`isnull` lookup no longer allows using non-boolean values as theright-hand side.* The ``django.db.models.query_utils.InvalidQuery`` exception class is removed.* The ``django-admin.py`` entry point is removed.* The ``HttpRequest.is_ajax()`` method is removed.* Support for the pre-Django 3.1 encoding format of cookies values used by``django.contrib.messages.storage.cookie.CookieStorage`` is removed.* Support for the pre-Django 3.1 password reset tokens in the admin site (thatuse the SHA-1 hashing algorithm) is removed.* Support for the pre-Django 3.1 encoding format of sessions is removed.* Support for the pre-Django 3.1 ``django.core.signing.Signer`` signatures(encoded with the SHA-1 algorithm) is removed.* Support for the pre-Django 3.1 ``django.core.signing.dumps()`` signatures(encoded with the SHA-1 algorithm) in ``django.core.signing.loads()`` isremoved.* Support for the pre-Django 3.1 user sessions (that use the SHA-1 algorithm)is removed.* The ``get_response`` argument for``django.utils.deprecation.MiddlewareMixin.__init__()`` is required anddoesn't accept ``None``.* The ``providing_args`` argument for ``django.dispatch.Signal`` is removed.* The ``length`` argument for ``django.utils.crypto.get_random_string()`` isrequired.* The ``list`` message for ``ModelMultipleChoiceField`` is removed.* Support for passing raw column aliases to ``QuerySet.order_by()`` is removed.* The ``NullBooleanField`` model field is removed, except for support inhistorical migrations.* ``django.conf.urls.url()`` is removed.* The ``django.contrib.postgres.fields.JSONField`` model field is removed,except for support in historical migrations.* ``django.contrib.postgres.fields.jsonb.KeyTransform`` and``django.contrib.postgres.fields.jsonb.KeyTextTransform`` are removed.* ``django.contrib.postgres.forms.JSONField`` is removed.* The ``{% ifequal %}`` and ``{% ifnotequal %}`` template tags are removed.* The ``DEFAULT_HASHING_ALGORITHM`` transitional setting is removed.