============================================ Django 4.1 release notes - UNDER DEVELOPMENT ============================================ *Expected August 2022* Welcome to Django 4.1! These release notes cover the :ref:`new features `, as well as some :ref:`backwards incompatible changes ` you'll want to be aware of when upgrading from Django 4.0 or earlier. We've :ref:`begun the deprecation process for some features `. See the :doc:`/howto/upgrade-version` guide if you're updating an existing project. Python compatibility ==================== Django 4.1 supports Python 3.8, 3.9, and 3.10. We **highly recommend** and only officially support the latest release of each series. .. _whats-new-4.1: What's new in Django 4.1 ======================== Asynchronous handlers for class-based views ------------------------------------------- View subclasses may now define async HTTP method handlers:: import asyncio from django.http import HttpResponse from django.views import View class AsyncView(View): async def get(self, request, *args, **kwargs): # Perform view logic using await. await asyncio.sleep(1) return HttpResponse("Hello async world!") See :ref:`async-class-based-views` for more details. .. _csrf-cookie-masked-usage: ``CSRF_COOKIE_MASKED`` setting ------------------------------ The new :setting:`CSRF_COOKIE_MASKED` transitional setting allows specifying whether to mask the CSRF cookie. :class:`~django.middleware.csrf.CsrfViewMiddleware` no longer masks the CSRF cookie like it does the CSRF token in the DOM. If you are upgrading multiple instances of the same project to Django 4.1, you should set :setting:`CSRF_COOKIE_MASKED` to ``True`` during the transition, in order to allow compatibility with the older versions of Django. Once the transition to 4.1 is complete you can stop overriding :setting:`CSRF_COOKIE_MASKED`. This setting is deprecated as of this release and will be removed in Django 5.0. Minor features -------------- :mod:`django.contrib.admin` ~~~~~~~~~~~~~~~~~~~~~~~~~~~ * The admin :ref:`dark mode CSS variables ` are now applied in a separate stylesheet and template block. * :ref:`modeladmin-list-filters` providing custom ``FieldListFilter`` subclasses can now control the query string value separator when filtering for multiple values using the ``__in`` lookup. * The admin :meth:`history view ` is now paginated. * Related widget wrappers now have a link to object's change form. * The :meth:`.AdminSite.get_app_list` method now allows changing the order of apps and models on the admin index page. :mod:`django.contrib.admindocs` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ... :mod:`django.contrib.auth` ~~~~~~~~~~~~~~~~~~~~~~~~~~ * The default iteration count for the PBKDF2 password hasher is increased from 320,000 to 390,000. * The :meth:`.RemoteUserBackend.configure_user` method now allows synchronizing user attributes with attributes in a remote system such as an LDAP directory. :mod:`django.contrib.contenttypes` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ... :mod:`django.contrib.gis` ~~~~~~~~~~~~~~~~~~~~~~~~~ * The new :meth:`.GEOSGeometry.make_valid()` method allows converting invalid geometries to valid ones. :mod:`django.contrib.messages` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ... :mod:`django.contrib.postgres` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * The new :class:`BitXor() ` aggregate function returns an ``int`` of the bitwise ``XOR`` of all non-null input values. * :class:`~django.contrib.postgres.indexes.SpGistIndex` now supports covering indexes on PostgreSQL 14+. * :class:`~django.contrib.postgres.constraints.ExclusionConstraint` now supports covering exclusion constraints using SP-GiST indexes on PostgreSQL 14+. * The new ``default_bounds`` attribute of :attr:`DateTimeRangeField ` and :attr:`DecimalRangeField ` allows specifying bounds for list and tuple inputs. * :class:`~django.contrib.postgres.constraints.ExclusionConstraint` now allows specifying operator classes with the :class:`OpClass() ` expression. :mod:`django.contrib.redirects` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ... :mod:`django.contrib.sessions` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ... :mod:`django.contrib.sitemaps` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * The default sitemap index template ```` now includes the ```` timestamp where available, through the new :meth:`~django.contrib.sitemaps.Sitemap.get_latest_lastmod` method. Custom sitemap index templates should be updated for the adjusted :ref:`context variables `. :mod:`django.contrib.sites` ~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ... :mod:`django.contrib.staticfiles` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * :class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage` now replaces paths to CSS source map references with their hashed counterparts. :mod:`django.contrib.syndication` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ... Cache ~~~~~ * ... CSRF ~~~~ * ... Database backends ~~~~~~~~~~~~~~~~~ * Third-party database backends can now specify the minimum required version of the database using the ``DatabaseFeatures.minimum_database_version`` attribute which is a tuple (e.g. ``(10, 0)`` means "10.0"). If a minimum version is specified, backends must also implement ``DatabaseWrapper.get_database_version()``, which returns a tuple of the current database version. The backend's ``DatabaseWrapper.init_connection_state()`` method must call ``super()`` in order for the check to run. Decorators ~~~~~~~~~~ * ... Email ~~~~~ * ... Error Reporting ~~~~~~~~~~~~~~~ * ... File Storage ~~~~~~~~~~~~ * ... File Uploads ~~~~~~~~~~~~ * ... Forms ~~~~~ * The new :meth:`~django.forms.BoundField.legend_tag` allows rendering field labels in ```` tags via the new ``tag`` argument of :meth:`~django.forms.BoundField.label_tag`. * The new ``edit_only`` argument for :func:`.modelformset_factory` and :func:`.inlineformset_factory` allows preventing new objects creation. * The ``js`` and ``css`` class attributes of :doc:`Media ` now allow using hashable objects, not only path strings, as long as those objects implement the ``__html__()`` method (typically when decorated with the :func:`~django.utils.html.html_safe` decorator). * The new :attr:`.BoundField.use_fieldset` and :attr:`.Widget.use_fieldset` attributes help to identify widgets where its inputs should be grouped in a ``
`` with a ````. Generic Views ~~~~~~~~~~~~~ * ... Internationalization ~~~~~~~~~~~~~~~~~~~~ * The :func:`~django.conf.urls.i18n.i18n_patterns` function now supports languages with both scripts and regions. Logging ~~~~~~~ * ... Management Commands ~~~~~~~~~~~~~~~~~~~ * :option:`makemigrations --no-input` now logs default answers and reasons why migrations cannot be created. * The new :option:`makemigrations --scriptable` option diverts log output and input prompts to ``stderr``, writing only paths of generated migration files to ``stdout``. * The new :option:`migrate --prune` option allows deleting nonexistent migrations from the ``django_migrations`` table. * Python files created by :djadmin:`startproject`, :djadmin:`startapp`, :djadmin:`optimizemigration`, :djadmin:`makemigrations`, and :djadmin:`squashmigrations` are now formatted using the ``black`` command if it is present on your ``PATH``. * The new :djadmin:`optimizemigration` command allows optimizing operations for a migration. Migrations ~~~~~~~~~~ * ... Models ~~~~~~ * The ``order_by`` argument of the :class:`~django.db.models.expressions.Window` expression now accepts string references to fields and transforms. * The new :setting:`CONN_HEALTH_CHECKS` setting allows enabling health checks for :ref:`persistent database connections ` in order to reduce the number of failed requests, e.g. after database server restart. * :meth:`.QuerySet.bulk_create` now supports updating fields when a row insertion fails uniqueness constraints. This is supported on MariaDB, MySQL, PostgreSQL, and SQLite 3.24+. * :meth:`.QuerySet.iterator` now supports prefetching related objects as long as the ``chunk_size`` argument is provided. In older versions, no prefetching was done. * :class:`~django.db.models.Q` objects and querysets can now be combined using ``^`` as the exclusive or (``XOR``) operator. ``XOR`` is natively supported on MariaDB and MySQL. For databases that do not support ``XOR``, the query will be converted to an equivalent using ``AND``, ``OR``, and ``NOT``. * The new :ref:`Field.non_db_attrs ` attribute allows customizing attributes of fields that don't affect a column definition. Requests and Responses ~~~~~~~~~~~~~~~~~~~~~~ * :meth:`.HttpResponse.set_cookie` now supports :class:`~datetime.timedelta` objects for the ``max_age`` argument. Security ~~~~~~~~ * The new :setting:`SECRET_KEY_FALLBACKS` setting allows providing a list of values for secret key rotation. * The :setting:`SECURE_PROXY_SSL_HEADER` setting now supports a comma-separated list of protocols in the header value. Serialization ~~~~~~~~~~~~~ * ... Signals ~~~~~~~ * The :data:`~django.db.models.signals.pre_delete` and :data:`~django.db.models.signals.post_delete` signals now dispatch the ``origin`` of the deletion. Templates ~~~~~~~~~ * :tfilter:`json_script` template filter now allows wrapping in a ``