4.1.txt 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  1. ========================
  2. Django 4.1 release notes
  3. ========================
  4. *August 3, 2022*
  5. Welcome to Django 4.1!
  6. These release notes cover the :ref:`new features <whats-new-4.1>`, as well as
  7. some :ref:`backwards incompatible changes <backwards-incompatible-4.1>` you'll
  8. want to be aware of when upgrading from Django 4.0 or earlier. We've
  9. :ref:`begun the deprecation process for some features
  10. <deprecated-features-4.1>`.
  11. See the :doc:`/howto/upgrade-version` guide if you're updating an existing
  12. project.
  13. Python compatibility
  14. ====================
  15. Django 4.1 supports Python 3.8, 3.9, 3.10, and 3.11 (as of 4.1.3). We
  16. **highly recommend** and only officially support the latest release of each
  17. series.
  18. .. _whats-new-4.1:
  19. What's new in Django 4.1
  20. ========================
  21. Asynchronous handlers for class-based views
  22. -------------------------------------------
  23. View subclasses may now define async HTTP method handlers::
  24. import asyncio
  25. from django.http import HttpResponse
  26. from django.views import View
  27. class AsyncView(View):
  28. async def get(self, request, *args, **kwargs):
  29. # Perform view logic using await.
  30. await asyncio.sleep(1)
  31. return HttpResponse("Hello async world!")
  32. See :ref:`async-class-based-views` for more details.
  33. Asynchronous ORM interface
  34. --------------------------
  35. ``QuerySet`` now provides an asynchronous interface for all data access
  36. operations. These are named as-per the existing synchronous operations but with
  37. an ``a`` prefix, for example ``acreate()``, ``aget()``, and so on.
  38. The new interface allows you to write asynchronous code without needing to wrap
  39. ORM operations in ``sync_to_async()``::
  40. async for author in Author.objects.filter(name__startswith="A"):
  41. book = await author.books.afirst()
  42. Note that, at this stage, the underlying database operations remain
  43. synchronous, with contributions ongoing to push asynchronous support down into
  44. the SQL compiler, and integrate asynchronous database drivers. The new
  45. asynchronous queryset interface currently encapsulates the necessary
  46. ``sync_to_async()`` operations for you, and will allow your code to take
  47. advantage of developments in the ORM's asynchronous support as it evolves.
  48. See :ref:`async-queries` for details and limitations.
  49. Validation of Constraints
  50. -------------------------
  51. :class:`Check <django.db.models.CheckConstraint>`,
  52. :class:`unique <django.db.models.UniqueConstraint>`, and :class:`exclusion
  53. <django.contrib.postgres.constraints.ExclusionConstraint>` constraints defined
  54. in the :attr:`Meta.constraints <django.db.models.Options.constraints>` option
  55. are now checked during :ref:`model validation <validating-objects>`.
  56. Form rendering accessibility
  57. ----------------------------
  58. In order to aid users with screen readers, and other assistive technology, new
  59. ``<div>`` based form templates are available from this release. These provide
  60. more accessible navigation than the older templates, and are able to correctly
  61. group related controls, such as radio-lists, into fieldsets.
  62. The new templates are recommended, and will become the default form rendering
  63. style when outputting a form, like ``{{ form }}`` in a template, from Django
  64. 5.0.
  65. In order to ease adopting the new output style, the default form and formset
  66. templates are now configurable at the project level via the
  67. :setting:`FORM_RENDERER` setting.
  68. See :ref:`the Forms section (below)<forms-4.1>` for full details.
  69. .. _csrf-cookie-masked-usage:
  70. ``CSRF_COOKIE_MASKED`` setting
  71. ------------------------------
  72. The new ``CSRF_COOKIE_MASKED`` transitional setting allows specifying whether
  73. to mask the CSRF cookie.
  74. :class:`~django.middleware.csrf.CsrfViewMiddleware` no longer masks the CSRF
  75. cookie like it does the CSRF token in the DOM. If you are upgrading multiple
  76. instances of the same project to Django 4.1, you should set
  77. ``CSRF_COOKIE_MASKED`` to ``True`` during the transition, in order to allow
  78. compatibility with the older versions of Django. Once the transition to 4.1 is
  79. complete you can stop overriding ``CSRF_COOKIE_MASKED``.
  80. This setting is deprecated as of this release and will be removed in Django
  81. 5.0.
  82. Minor features
  83. --------------
  84. :mod:`django.contrib.admin`
  85. ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  86. * The admin :ref:`dark mode CSS variables <admin-theming>` are now applied in a
  87. separate stylesheet and template block.
  88. * :ref:`modeladmin-list-filters` providing custom ``FieldListFilter``
  89. subclasses can now control the query string value separator when filtering
  90. for multiple values using the ``__in`` lookup.
  91. * The admin :meth:`history view <django.contrib.admin.ModelAdmin.history_view>`
  92. is now paginated.
  93. * Related widget wrappers now have a link to object's change form.
  94. * The :meth:`.AdminSite.get_app_list` method now allows changing the order of
  95. apps and models on the admin index page.
  96. :mod:`django.contrib.auth`
  97. ~~~~~~~~~~~~~~~~~~~~~~~~~~
  98. * The default iteration count for the PBKDF2 password hasher is increased from
  99. 320,000 to 390,000.
  100. * The :meth:`.RemoteUserBackend.configure_user` method now allows synchronizing
  101. user attributes with attributes in a remote system such as an LDAP directory.
  102. :mod:`django.contrib.gis`
  103. ~~~~~~~~~~~~~~~~~~~~~~~~~
  104. * The new :meth:`.GEOSGeometry.make_valid()` method allows converting invalid
  105. geometries to valid ones.
  106. * The new ``clone`` argument for :meth:`.GEOSGeometry.normalize` allows
  107. creating a normalized clone of the geometry.
  108. :mod:`django.contrib.postgres`
  109. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  110. * The new :class:`BitXor() <django.contrib.postgres.aggregates.BitXor>`
  111. aggregate function returns an ``int`` of the bitwise ``XOR`` of all non-null
  112. input values.
  113. * :class:`~django.contrib.postgres.indexes.SpGistIndex` now supports covering
  114. indexes on PostgreSQL 14+.
  115. * :class:`~django.contrib.postgres.constraints.ExclusionConstraint` now
  116. supports covering exclusion constraints using SP-GiST indexes on PostgreSQL
  117. 14+.
  118. * The new ``default_bounds`` attribute of :attr:`DateTimeRangeField
  119. <django.contrib.postgres.fields.DateTimeRangeField.default_bounds>` and
  120. :attr:`DecimalRangeField
  121. <django.contrib.postgres.fields.DecimalRangeField.default_bounds>` allows
  122. specifying bounds for list and tuple inputs.
  123. * :class:`~django.contrib.postgres.constraints.ExclusionConstraint` now allows
  124. specifying operator classes with the
  125. :class:`OpClass() <django.contrib.postgres.indexes.OpClass>` expression.
  126. :mod:`django.contrib.sitemaps`
  127. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  128. * The default sitemap index template ``<sitemapindex>`` now includes the
  129. ``<lastmod>`` timestamp where available, through the new
  130. :meth:`~django.contrib.sitemaps.Sitemap.get_latest_lastmod` method. Custom
  131. sitemap index templates should be updated for the adjusted :ref:`context
  132. variables <sitemap-index-context-variables>`.
  133. :mod:`django.contrib.staticfiles`
  134. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  135. * :class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage` now
  136. replaces paths to CSS source map references with their hashed counterparts.
  137. Database backends
  138. ~~~~~~~~~~~~~~~~~
  139. * Third-party database backends can now specify the minimum required version of
  140. the database using the ``DatabaseFeatures.minimum_database_version``
  141. attribute which is a tuple (e.g. ``(10, 0)`` means "10.0"). If a minimum
  142. version is specified, backends must also implement
  143. ``DatabaseWrapper.get_database_version()``, which returns a tuple of the
  144. current database version. The backend's
  145. ``DatabaseWrapper.init_connection_state()`` method must call ``super()`` in
  146. order for the check to run.
  147. .. _forms-4.1:
  148. Forms
  149. ~~~~~
  150. * The default template used to render forms when cast to a string, e.g. in
  151. templates as ``{{ form }}``, is now configurable at the project-level by
  152. setting :attr:`~django.forms.renderers.BaseRenderer.form_template_name` on
  153. the class provided for :setting:`FORM_RENDERER`.
  154. :attr:`.Form.template_name` is now a property deferring to the renderer, but
  155. may be overridden with a string value to specify the template name per-form
  156. class.
  157. Similarly, the default template used to render formsets can be specified via
  158. the matching
  159. :attr:`~django.forms.renderers.BaseRenderer.formset_template_name` renderer
  160. attribute.
  161. * The new ``div.html`` form template, referencing
  162. :attr:`.Form.template_name_div` attribute, and matching :meth:`.Form.as_div`
  163. method, render forms using HTML ``<div>`` elements.
  164. This new output style is recommended over the existing
  165. :meth:`~.Form.as_table`, :meth:`~.Form.as_p` and :meth:`~.Form.as_ul` styles,
  166. as the template implements ``<fieldset>`` and ``<legend>`` to group related
  167. inputs and is easier for screen reader users to navigate.
  168. The div-based output will become the default rendering style from Django 5.0.
  169. * In order to smooth adoption of the new ``<div>`` output style, two
  170. transitional form renderer classes are available:
  171. :class:`django.forms.renderers.DjangoDivFormRenderer` and
  172. :class:`django.forms.renderers.Jinja2DivFormRenderer`, for the Django and
  173. Jinja2 template backends respectively.
  174. You can apply one of these via the :setting:`FORM_RENDERER` setting. For
  175. example::
  176. FORM_RENDERER = "django.forms.renderers.DjangoDivFormRenderer"
  177. Once the ``<div>`` output style is the default, from Django 5.0, these
  178. transitional renderers will be deprecated, for removal in Django 6.0. The
  179. ``FORM_RENDERER`` declaration can be removed at that time.
  180. * If the new ``<div>`` output style is not appropriate for your project, you should
  181. define a renderer subclass specifying
  182. :attr:`~django.forms.renderers.BaseRenderer.form_template_name` and
  183. :attr:`~django.forms.renderers.BaseRenderer.formset_template_name` for your
  184. required style, and set :setting:`FORM_RENDERER` accordingly.
  185. For example, for the ``<p>`` output style used by :meth:`~.Form.as_p`, you
  186. would define a form renderer setting ``form_template_name`` to
  187. ``"django/forms/p.html"`` and ``formset_template_name`` to
  188. ``"django/forms/formsets/p.html"``.
  189. * The new :meth:`~django.forms.BoundField.legend_tag` allows rendering field
  190. labels in ``<legend>`` tags via the new ``tag`` argument of
  191. :meth:`~django.forms.BoundField.label_tag`.
  192. * The new ``edit_only`` argument for :func:`.modelformset_factory` and
  193. :func:`.inlineformset_factory` allows preventing new objects creation.
  194. * The ``js`` and ``css`` class attributes of :doc:`Media </topics/forms/media>`
  195. now allow using hashable objects, not only path strings, as long as those
  196. objects implement the ``__html__()`` method (typically when decorated with
  197. the :func:`~django.utils.html.html_safe` decorator).
  198. * The new :attr:`.BoundField.use_fieldset` and :attr:`.Widget.use_fieldset`
  199. attributes help to identify widgets where its inputs should be grouped in a
  200. ``<fieldset>`` with a ``<legend>``.
  201. * The :ref:`formsets-error-messages` argument for
  202. :class:`~django.forms.formsets.BaseFormSet` now allows customizing
  203. error messages for invalid number of forms by passing ``'too_few_forms'``
  204. and ``'too_many_forms'`` keys.
  205. * :class:`~django.forms.IntegerField`, :class:`~django.forms.FloatField`, and
  206. :class:`~django.forms.DecimalField` now optionally accept a ``step_size``
  207. argument. This is used to set the ``step`` HTML attribute, and is validated
  208. on form submission.
  209. Internationalization
  210. ~~~~~~~~~~~~~~~~~~~~
  211. * The :func:`~django.conf.urls.i18n.i18n_patterns` function now supports
  212. languages with both scripts and regions.
  213. Management Commands
  214. ~~~~~~~~~~~~~~~~~~~
  215. * :option:`makemigrations --no-input` now logs default answers and reasons why
  216. migrations cannot be created.
  217. * The new :option:`makemigrations --scriptable` option diverts log output and
  218. input prompts to ``stderr``, writing only paths of generated migration files
  219. to ``stdout``.
  220. * The new :option:`migrate --prune` option allows deleting nonexistent
  221. migrations from the ``django_migrations`` table.
  222. * Python files created by :djadmin:`startproject`, :djadmin:`startapp`,
  223. :djadmin:`optimizemigration`, :djadmin:`makemigrations`, and
  224. :djadmin:`squashmigrations` are now formatted using the ``black`` command if
  225. it is present on your ``PATH``.
  226. * The new :djadmin:`optimizemigration` command allows optimizing operations for
  227. a migration.
  228. Migrations
  229. ~~~~~~~~~~
  230. * The new :class:`~django.db.migrations.operations.RenameIndex` operation
  231. allows renaming indexes defined in the
  232. :attr:`Meta.indexes <django.db.models.Options.indexes>` or
  233. :attr:`~django.db.models.Options.index_together` options.
  234. * The migrations autodetector now generates
  235. :class:`~django.db.migrations.operations.RenameIndex` operations instead of
  236. ``RemoveIndex`` and ``AddIndex``, when renaming indexes defined in the
  237. :attr:`Meta.indexes <django.db.models.Options.indexes>`.
  238. * The migrations autodetector now generates
  239. :class:`~django.db.migrations.operations.RenameIndex` operations instead of
  240. ``AlterIndexTogether`` and ``AddIndex``, when moving indexes defined in the
  241. :attr:`Meta.index_together <django.db.models.Options.index_together>` to the
  242. :attr:`Meta.indexes <django.db.models.Options.indexes>`.
  243. Models
  244. ~~~~~~
  245. * The ``order_by`` argument of the
  246. :class:`~django.db.models.expressions.Window` expression now accepts string
  247. references to fields and transforms.
  248. * The new :setting:`CONN_HEALTH_CHECKS` setting allows enabling health checks
  249. for :ref:`persistent database connections <persistent-database-connections>`
  250. in order to reduce the number of failed requests, e.g. after database server
  251. restart.
  252. * :meth:`.QuerySet.bulk_create` now supports updating fields when a row
  253. insertion fails uniqueness constraints. This is supported on MariaDB, MySQL,
  254. PostgreSQL, and SQLite 3.24+.
  255. * :meth:`.QuerySet.iterator` now supports prefetching related objects as long
  256. as the ``chunk_size`` argument is provided. In older versions, no prefetching
  257. was done.
  258. * :class:`~django.db.models.Q` objects and querysets can now be combined using
  259. ``^`` as the exclusive or (``XOR``) operator. ``XOR`` is natively supported
  260. on MariaDB and MySQL. For databases that do not support ``XOR``, the query
  261. will be converted to an equivalent using ``AND``, ``OR``, and ``NOT``.
  262. * The new :ref:`Field.non_db_attrs <custom-field-non_db_attrs>` attribute
  263. allows customizing attributes of fields that don't affect a column
  264. definition.
  265. * On PostgreSQL, ``AutoField``, ``BigAutoField``, and ``SmallAutoField`` are
  266. now created as identity columns rather than serial columns with sequences.
  267. Requests and Responses
  268. ~~~~~~~~~~~~~~~~~~~~~~
  269. * :meth:`.HttpResponse.set_cookie` now supports :class:`~datetime.timedelta`
  270. objects for the ``max_age`` argument.
  271. Security
  272. ~~~~~~~~
  273. * The new :setting:`SECRET_KEY_FALLBACKS` setting allows providing a list of
  274. values for secret key rotation.
  275. * The :setting:`SECURE_PROXY_SSL_HEADER` setting now supports a comma-separated
  276. list of protocols in the header value.
  277. Signals
  278. ~~~~~~~
  279. * The :data:`~django.db.models.signals.pre_delete` and
  280. :data:`~django.db.models.signals.post_delete` signals now dispatch the
  281. ``origin`` of the deletion.
  282. .. _templates-4.1:
  283. Templates
  284. ~~~~~~~~~
  285. * The HTML ``<script>`` element ``id`` attribute is no longer required when
  286. wrapping the :tfilter:`json_script` template filter.
  287. * The :class:`cached template loader <django.template.loaders.cached.Loader>`
  288. is now enabled in development, when :setting:`DEBUG` is ``True``, and
  289. :setting:`OPTIONS['loaders'] <TEMPLATES-OPTIONS>` isn't specified. You may
  290. specify ``OPTIONS['loaders']`` to override this, if necessary.
  291. Tests
  292. ~~~~~
  293. * The :class:`.DiscoverRunner` now supports running tests in parallel on
  294. macOS, Windows, and any other systems where the default
  295. :mod:`multiprocessing` start method is ``spawn``.
  296. * A nested atomic block marked as durable in :class:`django.test.TestCase` now
  297. raises a ``RuntimeError``, the same as outside of tests.
  298. * :meth:`.SimpleTestCase.assertFormError` and
  299. :meth:`assertFormsetError() <django.test.SimpleTestCase.assertFormSetError>`
  300. now support passing a form/formset object directly.
  301. URLs
  302. ~~~~
  303. * The new :attr:`.ResolverMatch.captured_kwargs` attribute stores the captured
  304. keyword arguments, as parsed from the URL.
  305. * The new :attr:`.ResolverMatch.extra_kwargs` attribute stores the additional
  306. keyword arguments passed to the view function.
  307. Utilities
  308. ~~~~~~~~~
  309. * ``SimpleLazyObject`` now supports addition operations.
  310. * :func:`~django.utils.safestring.mark_safe` now preserves lazy objects.
  311. Validators
  312. ~~~~~~~~~~
  313. * The new :class:`~django.core.validators.StepValueValidator` checks if a value
  314. is an integral multiple of a given step size. This new validator is used for
  315. the new ``step_size`` argument added to form fields representing numeric
  316. values.
  317. .. _backwards-incompatible-4.1:
  318. Backwards incompatible changes in 4.1
  319. =====================================
  320. Database backend API
  321. --------------------
  322. This section describes changes that may be needed in third-party database
  323. backends.
  324. * ``BaseDatabaseFeatures.has_case_insensitive_like`` is changed from ``True``
  325. to ``False`` to reflect the behavior of most databases.
  326. * ``DatabaseIntrospection.get_key_columns()`` is removed. Use
  327. ``DatabaseIntrospection.get_relations()`` instead.
  328. * ``DatabaseOperations.ignore_conflicts_suffix_sql()`` method is replaced by
  329. ``DatabaseOperations.on_conflict_suffix_sql()`` that accepts the ``fields``,
  330. ``on_conflict``, ``update_fields``, and ``unique_fields`` arguments.
  331. * The ``ignore_conflicts`` argument of the
  332. ``DatabaseOperations.insert_statement()`` method is replaced by
  333. ``on_conflict`` that accepts ``django.db.models.constants.OnConflict``.
  334. * ``DatabaseOperations._convert_field_to_tz()`` is replaced by
  335. ``DatabaseOperations._convert_sql_to_tz()`` that accepts the ``sql``,
  336. ``params``, and ``tzname`` arguments.
  337. * Several date and time methods on ``DatabaseOperations`` now take ``sql`` and
  338. ``params`` arguments instead of ``field_name`` and return 2-tuple containing
  339. some SQL and the parameters to be interpolated into that SQL. The changed
  340. methods have these new signatures:
  341. * ``DatabaseOperations.date_extract_sql(lookup_type, sql, params)``
  342. * ``DatabaseOperations.datetime_extract_sql(lookup_type, sql, params, tzname)``
  343. * ``DatabaseOperations.time_extract_sql(lookup_type, sql, params)``
  344. * ``DatabaseOperations.date_trunc_sql(lookup_type, sql, params, tzname=None)``
  345. * ``DatabaseOperations.datetime_trunc_sql(self, lookup_type, sql, params, tzname)``
  346. * ``DatabaseOperations.time_trunc_sql(lookup_type, sql, params, tzname=None)``
  347. * ``DatabaseOperations.datetime_cast_date_sql(sql, params, tzname)``
  348. * ``DatabaseOperations.datetime_cast_time_sql(sql, params, tzname)``
  349. :mod:`django.contrib.gis`
  350. -------------------------
  351. * Support for GDAL 2.1 is removed.
  352. * Support for PostGIS 2.4 is removed.
  353. Dropped support for PostgreSQL 10
  354. ---------------------------------
  355. Upstream support for PostgreSQL 10 ends in November 2022. Django 4.1 supports
  356. PostgreSQL 11 and higher.
  357. Dropped support for MariaDB 10.2
  358. --------------------------------
  359. Upstream support for MariaDB 10.2 ends in May 2022. Django 4.1 supports MariaDB
  360. 10.3 and higher.
  361. Admin changelist searches spanning multi-valued relationships changes
  362. ---------------------------------------------------------------------
  363. Admin changelist searches using multiple search terms are now applied in a
  364. single call to ``filter()``, rather than in sequential ``filter()`` calls.
  365. For multi-valued relationships, this means that rows from the related model
  366. must match all terms rather than any term. For example, if ``search_fields``
  367. is set to ``['child__name', 'child__age']``, and a user searches for
  368. ``'Jamal 17'``, parent rows will be returned only if there is a relationship to
  369. some 17-year-old child named Jamal, rather than also returning parents who
  370. merely have a younger or older child named Jamal in addition to some other
  371. 17-year-old.
  372. See the :ref:`spanning-multi-valued-relationships` topic for more discussion of
  373. this difference. In Django 4.0 and earlier,
  374. :meth:`~django.contrib.admin.ModelAdmin.get_search_results` followed the
  375. second example query, but this undocumented behavior led to queries with
  376. excessive joins.
  377. Reverse foreign key changes for unsaved model instances
  378. -------------------------------------------------------
  379. In order to unify the behavior with many-to-many relations for unsaved model
  380. instances, a reverse foreign key now raises ``ValueError`` when calling
  381. :class:`related managers <django.db.models.fields.related.RelatedManager>` for
  382. unsaved objects.
  383. Miscellaneous
  384. -------------
  385. * Related managers for :class:`~django.db.models.ForeignKey`,
  386. :class:`~django.db.models.ManyToManyField`, and
  387. :class:`~django.contrib.contenttypes.fields.GenericRelation` are now cached
  388. on the :class:`~django.db.models.Model` instance to which they belong. *This
  389. change was reverted in Django 4.1.2.*
  390. * The Django test runner now returns a non-zero error code for unexpected
  391. successes from tests marked with :py:func:`unittest.expectedFailure`.
  392. * :class:`~django.middleware.csrf.CsrfViewMiddleware` no longer masks the CSRF
  393. cookie like it does the CSRF token in the DOM.
  394. * :class:`~django.middleware.csrf.CsrfViewMiddleware` now uses
  395. ``request.META['CSRF_COOKIE']`` for storing the unmasked CSRF secret rather
  396. than a masked version. This is an undocumented, private API.
  397. * The :attr:`.ModelAdmin.actions` and
  398. :attr:`~django.contrib.admin.ModelAdmin.inlines` attributes now default to an
  399. empty tuple rather than an empty list to discourage unintended mutation.
  400. * The ``type="text/css"`` attribute is no longer included in ``<link>`` tags
  401. for CSS :doc:`form media </topics/forms/media>`.
  402. * ``formset:added`` and ``formset:removed`` JavaScript events are now pure
  403. JavaScript events and don't depend on jQuery. See
  404. :ref:`admin-javascript-inline-form-events` for more details on the change.
  405. * The ``exc_info`` argument of the undocumented
  406. ``django.utils.log.log_response()`` function is replaced by ``exception``.
  407. * The ``size`` argument of the undocumented
  408. ``django.views.static.was_modified_since()`` function is removed.
  409. * The admin log out UI now uses ``POST`` requests.
  410. * The undocumented ``InlineAdminFormSet.non_form_errors`` property is replaced
  411. by the ``non_form_errors()`` method. This is consistent with ``BaseFormSet``.
  412. * As per :ref:`above<templates-4.1>`, the cached template loader is now
  413. enabled in development. You may specify ``OPTIONS['loaders']`` to override
  414. this, if necessary.
  415. * The undocumented ``django.contrib.auth.views.SuccessURLAllowedHostsMixin``
  416. mixin is replaced by ``RedirectURLMixin``.
  417. * :class:`~django.db.models.BaseConstraint` subclasses must implement
  418. :meth:`~django.db.models.BaseConstraint.validate` method to allow those
  419. constraints to be used for validation.
  420. * The undocumented ``URLResolver._is_callback()``,
  421. ``URLResolver._callback_strs``, and ``URLPattern.lookup_str()`` are
  422. moved to ``django.contrib.admindocs.utils``.
  423. * The :meth:`.Model.full_clean` method now converts an ``exclude`` value to a
  424. ``set``. It’s also preferable to pass an ``exclude`` value as a ``set`` to
  425. the :meth:`.Model.clean_fields`, :meth:`.Model.full_clean`,
  426. :meth:`.Model.validate_unique`, and :meth:`.Model.validate_constraints`
  427. methods.
  428. * The minimum supported version of ``asgiref`` is increased from 3.4.1 to
  429. 3.5.2.
  430. * Combined expressions no longer use the error-prone behavior of guessing
  431. ``output_field`` when argument types match. As a consequence, resolving an
  432. ``output_field`` for database functions and combined expressions may now
  433. crash with mixed types. You will need to explicitly set the ``output_field``
  434. in such cases.
  435. .. _deprecated-features-4.1:
  436. Features deprecated in 4.1
  437. ==========================
  438. Log out via GET
  439. ---------------
  440. Logging out via ``GET`` requests to the :py:class:`built-in logout view
  441. <django.contrib.auth.views.LogoutView>` is deprecated. Use ``POST`` requests
  442. instead.
  443. If you want to retain the user experience of an HTML link, you can use a form
  444. that is styled to appear as a link:
  445. .. code-block:: html
  446. <form id="logout-form" method="post" action="{% url 'admin:logout' %}">
  447. {% csrf_token %}
  448. <button type="submit">{% translate "Log out" %}</button>
  449. </form>
  450. .. code-block:: css
  451. #logout-form {
  452. display: inline;
  453. }
  454. #logout-form button {
  455. background: none;
  456. border: none;
  457. cursor: pointer;
  458. padding: 0;
  459. text-decoration: underline;
  460. }
  461. Miscellaneous
  462. -------------
  463. * The context for sitemap index templates of a flat list of URLs is deprecated.
  464. Custom sitemap index templates should be updated for the adjusted
  465. :ref:`context variables <sitemap-index-context-variables>`, expecting a list
  466. of objects with ``location`` and optional ``lastmod`` attributes.
  467. * ``CSRF_COOKIE_MASKED`` transitional setting is deprecated.
  468. * The ``name`` argument of :func:`django.utils.functional.cached_property` is
  469. deprecated as it's unnecessary as of Python 3.6.
  470. * The ``opclasses`` argument of
  471. ``django.contrib.postgres.constraints.ExclusionConstraint`` is deprecated in
  472. favor of using :class:`OpClass() <django.contrib.postgres.indexes.OpClass>`
  473. in :attr:`.ExclusionConstraint.expressions`. To use it, you need to add
  474. ``'django.contrib.postgres'`` in your :setting:`INSTALLED_APPS`.
  475. After making this change, :djadmin:`makemigrations` will generate a new
  476. migration with two operations: ``RemoveConstraint`` and ``AddConstraint``.
  477. Since this change has no effect on the database schema,
  478. the :class:`~django.db.migrations.operations.SeparateDatabaseAndState`
  479. operation can be used to only update the migration state without running any
  480. SQL. Move the generated operations into the ``state_operations`` argument of
  481. :class:`~django.db.migrations.operations.SeparateDatabaseAndState`. For
  482. example::
  483. class Migration(migrations.Migration):
  484. ...
  485. operations = [
  486. migrations.SeparateDatabaseAndState(
  487. database_operations=[],
  488. state_operations=[
  489. migrations.RemoveConstraint(
  490. ...
  491. ),
  492. migrations.AddConstraint(
  493. ...
  494. ),
  495. ],
  496. ),
  497. ]
  498. * The undocumented ability to pass ``errors=None`` to
  499. :meth:`.SimpleTestCase.assertFormError` and
  500. :meth:`assertFormsetError() <django.test.SimpleTestCase.assertFormSetError>`
  501. is deprecated. Use ``errors=[]`` instead.
  502. * ``django.contrib.sessions.serializers.PickleSerializer`` is deprecated due to
  503. the risk of remote code execution.
  504. * The usage of ``QuerySet.iterator()`` on a queryset that prefetches related
  505. objects without providing the ``chunk_size`` argument is deprecated. In older
  506. versions, no prefetching was done. Providing a value for ``chunk_size``
  507. signifies that the additional query per chunk needed to prefetch is desired.
  508. * Passing unsaved model instances to related filters is deprecated. In Django
  509. 5.0, the exception will be raised.
  510. * ``created=True`` is added to the signature of
  511. :meth:`.RemoteUserBackend.configure_user`. Support for ``RemoteUserBackend``
  512. subclasses that do not accept this argument is deprecated.
  513. * The :data:`django.utils.timezone.utc` alias to :attr:`datetime.timezone.utc`
  514. is deprecated. Use :attr:`datetime.timezone.utc` directly.
  515. * Passing a response object and a form/formset name to
  516. ``SimpleTestCase.assertFormError()`` and ``assertFormsetError()`` is
  517. deprecated. Use::
  518. assertFormError(response.context['form_name'], …)
  519. assertFormsetError(response.context['formset_name'], …)
  520. or pass the form/formset object directly instead.
  521. * The undocumented ``django.contrib.gis.admin.OpenLayersWidget`` is deprecated.
  522. * ``django.contrib.auth.hashers.CryptPasswordHasher`` is deprecated.
  523. * The ability to pass ``nulls_first=False`` or ``nulls_last=False`` to
  524. ``Expression.asc()`` and ``Expression.desc()`` methods, and the ``OrderBy``
  525. expression is deprecated. Use ``None`` instead.
  526. * The ``"django/forms/default.html"`` and
  527. ``"django/forms/formsets/default.html"`` templates which are a proxy to the
  528. table-based templates are deprecated. Use the specific template instead.
  529. * The undocumented ``LogoutView.get_next_page()`` method is renamed to
  530. ``get_success_url()``.
  531. Features removed in 4.1
  532. =======================
  533. These features have reached the end of their deprecation cycle and are removed
  534. in Django 4.1.
  535. See :ref:`deprecated-features-3.2` for details on these changes, including how
  536. to remove usage of these features.
  537. * Support for assigning objects which don't support creating deep copies with
  538. ``copy.deepcopy()`` to class attributes in ``TestCase.setUpTestData()`` is
  539. removed.
  540. * Support for using a boolean value in
  541. :attr:`.BaseCommand.requires_system_checks` is removed.
  542. * The ``whitelist`` argument and ``domain_whitelist`` attribute of
  543. ``django.core.validators.EmailValidator`` are removed.
  544. * The ``default_app_config`` application configuration variable is removed.
  545. * ``TransactionTestCase.assertQuerysetEqual()`` no longer calls ``repr()`` on a
  546. queryset when compared to string values.
  547. * The ``django.core.cache.backends.memcached.MemcachedCache`` backend is
  548. removed.
  549. * Support for the pre-Django 3.2 format of messages used by
  550. ``django.contrib.messages.storage.cookie.CookieStorage`` is removed.