Примечания к выпуску Django 4.1¶
3 августа 2022 года
Добро пожаловать в Django 4.1!
Эти заметки о выпуске охватывают new features, а также некоторые backwards incompatible changes, о которых вы должны знать при переходе с Django 4.0 или более ранней версии. Мы begun the deprecation process for some features.
См. руководство Как обновить Django до более новой версии, если вы обновляете существующий проект.
Совместимость с Python¶
Django 4.1 поддерживает Python 3.8, 3.9, 3.10 и 3.11 (начиная с версии 4.1.3). Мы настоятельно рекомендуем и официально поддерживаем только последний релиз каждой серии.
Что нового в Django 4.1¶
Асинхронные обработчики для представлений на основе классов¶
Подклассы представления теперь могут определять асинхронные обработчики HTTP-методов:
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!")
Более подробную информацию см. в разделе Асинхронные представления на основе классов.
Асинхронный интерфейс ORM¶
QuerySet
теперь предоставляет асинхронный интерфейс для всех операций доступа к данным. Они называются так же, как и существующие синхронные операции, но с префиксом a
, например acreate()
, aget()
и так далее.
Новый интерфейс позволяет писать асинхронный код без необходимости оборачивать операции ORM в sync_to_async()
:
async for author in Author.objects.filter(name__startswith="A"):
book = await author.books.afirst()
Обратите внимание, что на данном этапе базовые операции с базой данных остаются синхронными, при этом продолжается работа по внедрению асинхронной поддержки в компилятор SQL и интеграции драйверов асинхронных баз данных. Новый асинхронный интерфейс queryset в настоящее время инкапсулирует необходимые операции sync_to_async()
для вас, и позволит вашему коду использовать преимущества развития асинхронной поддержки ORM по мере его развития.
Подробности и ограничения см. в разделе Асинхронные запросы.
Валидация ограничений¶
Ограничения Check
, unique
и exclusion
, определенные в опции Meta.constraints
, теперь проверяются во время model validation.
Доступность рендеринга формы¶
Чтобы помочь пользователям с программами чтения с экрана и другими вспомогательными технологиями, в этом выпуске доступны новые шаблоны форм на основе <div>
. Они обеспечивают более доступную навигацию, чем старые шаблоны, и способны правильно группировать связанные элементы управления, такие как радиосписки, в наборы полей.
Новые шаблоны рекомендованы и станут стилем рендеринга формы по умолчанию при выводе формы, как {{ form }}
в шаблоне, начиная с Django 5.0.
Чтобы облегчить принятие нового стиля вывода, шаблоны форм и наборов форм по умолчанию теперь настраиваются на уровне проекта с помощью параметра FORM_RENDERER
.
Подробную информацию см. в разделе the Forms section (below).
CSRF_COOKIE_MASKED
установка¶
Новая переходная настройка CSRF_COOKIE_MASKED
позволяет указать, нужно ли маскировать CSRF-куки.
CsrfViewMiddleware
больше не маскирует CSRF-куки, как это делает CSRF-токен в DOM. Если вы обновляете несколько экземпляров одного и того же проекта до Django 4.1, вам следует установить CSRF_COOKIE_MASKED
на True
во время перехода, чтобы обеспечить совместимость со старыми версиями Django. После завершения перехода на 4.1 вы можете перестать переопределять CSRF_COOKIE_MASKED
.
Эта настройка устарела в этом выпуске и будет удалена в Django 5.0.
Незначительные особенности¶
django.contrib.admin
¶
- Админ dark mode CSS variables теперь применяется в отдельной таблице стилей и блоке шаблона.
- ModelAdmin Фильтры списка, предоставляющие пользовательские подклассы
FieldListFilter
, теперь могут управлять разделителем значений строки запроса при фильтрации нескольких значений с помощью поиска__in
. - Администратор
history view
теперь постранично. - В обертках связанных виджетов теперь есть ссылка на форму изменения объекта.
- Метод
AdminSite.get_app_list()
теперь позволяет изменить порядок приложений и моделей на индексной странице администратора.
django.contrib.auth
¶
- Число итераций по умолчанию для хешера паролей PBKDF2 увеличено с 320 000 до 390 000.
- Метод
RemoteUserBackend.configure_user()
теперь позволяет синхронизировать атрибуты пользователя с атрибутами в удаленной системе, такой как каталог LDAP.
django.contrib.gis
¶
- Новый метод
GEOSGeometry.make_valid()
позволяет преобразовывать недопустимые геометрии в допустимые. - Новый аргумент
clone
дляGEOSGeometry.normalize()
позволяет создать нормализованный клон геометрии.
django.contrib.postgres
¶
- Новая агрегатная функция
BitXor()
возвращаетint
побитовогоXOR
всех не нулевых входных значений. SpGistIndex
теперь поддерживает покрывающие индексы на PostgreSQL 14+.ExclusionConstraint
теперь поддерживает охватывающие ограничения исключения с использованием индексов SP-GiST на PostgreSQL 14+.- Новый атрибут
default_bounds
вDateTimeRangeField
иDecimalRangeField
позволяет задавать границы для списков и кортежей. ExclusionConstraint
теперь позволяет указывать классы операторов с помощью выраженияOpClass()
.
django.contrib.sitemaps
¶
- Шаблон индекса карты сайта по умолчанию
<sitemapindex>
теперь включает метку времени<lastmod>
там, где она доступна, с помощью нового методаget_latest_lastmod()
. Пользовательские шаблоны индекса sitemap должны быть обновлены для корректировки context variables.
django.contrib.staticfiles
¶
ManifestStaticFilesStorage
теперь заменяет пути к ссылкам на карту источников CSS их хэшированными аналогами.
Бэкенды баз данных¶
- Бэкенды баз данных сторонних производителей теперь могут указывать минимально необходимую версию базы данных с помощью атрибута
DatabaseFeatures.minimum_database_version
, который представляет собой кортеж (например,(10, 0)
означает «10.0»). Если указана минимальная версия, бэкенды должны также реализоватьDatabaseWrapper.get_database_version()
, который возвращает кортеж текущей версии базы данных. Метод бэкендаDatabaseWrapper.init_connection_state()
должен вызватьsuper()
для того, чтобы проверка была выполнена.
Формы¶
Шаблон по умолчанию, используемый для отображения форм при приведении к строке, например, в шаблонах в виде
{{ form }}
, теперь настраивается на уровне проекта путем установкиform_template_name
на класс, предусмотренный дляFORM_RENDERER
.Form.template_name
теперь является свойством, отсылающим к рендереру, но может быть переопределено строковым значением для указания имени шаблона per-form class.Аналогично, шаблон по умолчанию, используемый для рендеринга наборов форм, может быть указан через соответствующий атрибут рендеринга
formset_template_name
.Новый шаблон формы
div.html
, ссылающийся на атрибутForm.template_name_div
, и соответствующий методForm.as_div()
выводят формы, используя элементы HTML<div>
.Этот новый стиль вывода рекомендуется использовать вместо существующих стилей
as_table()
,as_p()
иas_ul()
, так как в шаблоне реализованы<fieldset>
и<legend>
для группировки связанных входов и более удобной навигации для пользователей программ чтения с экрана.Вывод на основе div станет стилем рендеринга по умолчанию, начиная с Django 5.0.
Чтобы сгладить переход на новый стиль вывода
<div>
, доступны два класса рендереров переходных форм:django.forms.renderers.DjangoDivFormRenderer
иdjango.forms.renderers.Jinja2DivFormRenderer
, для бэкендов шаблонов Django и Jinja2 соответственно.Вы можете применить один из них через настройку
FORM_RENDERER
. Например:FORM_RENDERER = "django.forms.renderers.DjangoDivFormRenderer"
Как только стиль вывода
<div>
станет стилем по умолчанию, начиная с Django 5.0, эти переходные рендереры будут устаревшими и будут удалены в Django 6.0. ОбъявлениеFORM_RENDERER
может быть удалено в это время.Если новый стиль вывода
<div>
не подходит для вашего проекта, вам следует определить подкласс рендерера, указавform_template_name
иformset_template_name
для требуемого стиля, и установитьFORM_RENDERER
соответственно.Например, для стиля вывода
<p>
, используемогоas_p()
, вы определите рендерер формы, устанавливающийform_template_name
в"django/forms/p.html"
иformset_template_name
в"django/forms/formsets/p.html"
.Новый
legend_tag()
позволяет выводить метки полей в тегах<legend>
через новый аргументtag
вlabel_tag()
.Новый аргумент
edit_only
дляmodelformset_factory()
иinlineformset_factory()
позволяет предотвратить создание новых объектов.Атрибуты класса
js
иcss
Media теперь позволяют использовать хешируемые объекты, а не только строки пути, если эти объекты реализуют__html__ ()
(обычно при декорировании с помощью декоратораhtml_safe()
).Новые атрибуты
BoundField.use_fieldset
иWidget.use_fieldset
помогают определить виджеты, в которых входы должны быть сгруппированы в<fieldset>
с<legend>
.Аргумент error_messages для
BaseFormSet
теперь позволяет настраивать сообщения об ошибках для недопустимого количества форм, передавая ключи'too_few_forms'
и'too_many_forms'
.IntegerField
,FloatField
иDecimalField
теперь опционально принимают аргументstep_size
. Он используется для установки HTML-атрибутаstep
и проверяется при отправке формы.
Интернационализация¶
- Функция
i18n_patterns()
теперь поддерживает языки со скриптами и регионами.
Команды управления¶
makemigrations --no-input
теперь записывает в журнал ответы по умолчанию и причины, по которым миграции не могут быть созданы.- Новая опция
makemigrations --scriptable
перенаправляет вывод журнала и подсказки ввода вstderr
, записывая вstdout
только пути сгенерированных файлов миграции. - Новая опция
migrate --prune
позволяет удалять несуществующие миграции из таблицыdjango_migrations
. - Файлы Python, созданные
startproject
,startapp
,optimizemigration
,makemigrations
иsquashmigrations
, теперь форматируются с помощью командыblack
, если она присутствует на вашемPATH
. - Новая команда
optimizemigration
позволяет оптимизировать операции для миграции.
Миграции¶
- Новая операция
RenameIndex
позволяет переименовывать индексы, определенные в параметрахMeta.indexes
илиindex_together
. - Автоопределитель миграций теперь генерирует операции
RenameIndex
вместоRemoveIndex
иAddIndex
при переименовании индексов, определенных вMeta.indexes
. - Автоопределитель миграции теперь генерирует операции
RenameIndex
вместоAlterIndexTogether
иAddIndex
при перемещении индексов, определенных вMeta.index_together
, вMeta.indexes
.
Модели¶
- Аргумент
order_by
выраженияWindow
теперь принимает строковые ссылки на поля и преобразования. - Новая настройка
CONN_HEALTH_CHECKS
позволяет включить проверку здоровья для persistent database connections, чтобы уменьшить количество неудачных запросов, например, после перезапуска сервера базы данных. QuerySet.bulk_create()
теперь поддерживает обновление полей, когда при вставке строки не соблюдаются ограничения уникальности. Это поддерживается на MariaDB, MySQL, PostgreSQL и SQLite 3.24+.QuerySet.iterator()
теперь поддерживает предварительную выборку связанных объектов, если указан аргументchunk_size
. В старых версиях предварительная выборка не выполнялась.- <<<Объекты
Q
и наборы запросов теперь можно объединять, используя^
в качестве оператора исключающего или (XOR
).XOR
поддерживается в MariaDB и MySQL. Для баз данных, не поддерживающихXOR
, запрос будет преобразован в эквивалент с помощьюAND
,OR
иNOT
. - Новый атрибут Field.non_db_attrs позволяет настраивать атрибуты полей, которые не влияют на определение столбца.
- В PostgreSQL столбцы
AutoField
,BigAutoField
иSmallAutoField
теперь создаются как столбцы идентичности, а не как последовательные столбцы с последовательностями.
Запросы и ответы¶
HttpResponse.set_cookie()
теперь поддерживает объектыtimedelta
для аргументаmax_age
.
Безопасность¶
- Новая настройка
SECRET_KEY_FALLBACKS
позволяет предоставить список значений для поворота секретного ключа. - Настройка
SECURE_PROXY_SSL_HEADER
теперь поддерживает список протоколов в значении заголовка, разделенный запятыми.
Сигналы¶
- Сигналы
pre_delete
иpost_delete
теперь отправляютorigin
удаления.
Шаблоны¶
- Атрибут HTML
<script>
элементаid
больше не требуется при обертывании фильтра шаблонаjson_script
. - Теперь
cached template loader
включается в разработке, когдаDEBUG
являетсяTrue
, аOPTIONS['loaders']
не указан. Вы можете указатьOPTIONS['loaders']
, чтобы отменить это, если необходимо.
Тесты¶
DiscoverRunner
теперь поддерживает параллельный запуск тестов на macOS, Windows и любых других системах, где по умолчанию используется метод запускаmultiprocessing
spawn
.- Вложенный атомарный блок, помеченный как долговечный в
django.test.TestCase
, теперь вызываетRuntimeError
, как и вне тестов. SimpleTestCase.assertFormError()
иassertFormsetError()
теперь поддерживают передачу объекта формы/formset напрямую.
URLs¶
- Новый атрибут
ResolverMatch.captured_kwargs
хранит захваченные аргументы ключевых слов, как они были разобраны из URL. - Новый атрибут
ResolverMatch.extra_kwargs
хранит дополнительные аргументы ключевого слова, переданные функции представления.
Утилиты¶
SimpleLazyObject
теперь поддерживает операции сложения.mark_safe()
теперь сохраняет ленивые объекты.
Валидаторы¶
- Новый
StepValueValidator
проверяет, является ли значение целым кратным заданного размера шага. Этот новый валидатор используется для нового аргументаstep_size
, добавляемого в поля формы, представляющие числовые значения.
Изменения в 4.1, несовместимые с обратными изменениями¶
API бэкенда базы данных¶
В этом разделе описаны изменения, которые могут потребоваться в бэкендах баз данных сторонних производителей.
BaseDatabaseFeatures.has_case_insensitive_like
изменено сTrue
наFalse
, чтобы отразить поведение большинства баз данных.DatabaseIntrospection.get_key_columns()
удаляется. Вместо этого используйтеDatabaseIntrospection.get_relations()
.- Метод
DatabaseOperations.ignore_conflicts_suffix_sql()
заменяется наDatabaseOperations.on_conflict_suffix_sql()
, который принимает аргументыfields
,on_conflict
,update_fields
иunique_fields
. - Аргумент
ignore_conflicts
методаDatabaseOperations.insert_statement()
заменяется наon_conflict
, который принимаетdjango.db.models.constants.OnConflict
. DatabaseOperations._convert_field_to_tz()
заменяется наDatabaseOperations._convert_sql_to_tz()
, который принимает аргументыsql
,params
иtzname
.- Несколько методов даты и времени на
DatabaseOperations
теперь принимают аргументыsql
иparams
вместоfield_name
и возвращают кортеж, содержащий некоторый SQL и параметры, которые должны быть интерполированы в этот SQL. Измененные методы имеют новые сигнатуры:DatabaseOperations.date_extract_sql(lookup_type, sql, params)
DatabaseOperations.datetime_extract_sql(lookup_type, sql, params, tzname)
DatabaseOperations.time_extract_sql(lookup_type, sql, params)
DatabaseOperations.date_trunc_sql(lookup_type, sql, params, tzname=None)
DatabaseOperations.datetime_trunc_sql(self, lookup_type, sql, params, tzname)
DatabaseOperations.time_trunc_sql(lookup_type, sql, params, tzname=None)
DatabaseOperations.datetime_cast_date_sql(sql, params, tzname)
DatabaseOperations.datetime_cast_time_sql(sql, params, tzname)
django.contrib.gis
¶
- Удалена поддержка GDAL 2.1.
- Удалена поддержка PostGIS 2.4.
Прекращена поддержка PostgreSQL 10¶
Поддержка PostgreSQL 10 заканчивается в ноябре 2022 года. Django 4.1 поддерживает PostgreSQL 11 и выше.
Прекращена поддержка MariaDB 10.2¶
Поддержка MariaDB 10.2 заканчивается в мае 2022 года. Django 4.1 поддерживает MariaDB 10.3 и выше.
Поиск изменений в списке изменений администратора, охватывающий изменения многозначных отношений¶
Поиск в списке изменений администратора с использованием нескольких поисковых запросов теперь выполняется в одном вызове filter()
, а не в последовательных вызовах filter()
.
Для многозначных отношений это означает, что строки из связанной модели должны соответствовать всем терминам, а не любому из них. Например, если search_fields
установлен на ['child__name', 'child__age']
, а пользователь ищет 'Jamal 17'
, строки о родителях будут возвращены только в том случае, если есть связь с каким-то 17-летним ребенком по имени Джамал, вместо того, чтобы возвращать родителям, у которых просто есть младший или старший ребенок по имени Джамал в дополнение к какому-то другому 17-летнему.
См. тему Охватывающие многозначные отношения для более подробного обсуждения этого различия. В Django 4.0 и более ранних версиях get_search_results()
следовал второму примеру запроса, но это недокументированное поведение приводило к запросам с избыточными соединениями.
Обратное изменение внешних ключей для несохраненных экземпляров модели¶
Чтобы унифицировать поведение с отношениями «многие ко многим» для несохраненных экземпляров модели, обратный внешний ключ теперь поднимает ValueError
при вызове related managers
для несохраненных объектов.
Разное¶
- Связанные менеджеры для
ForeignKey
,ManyToManyField
иGenericRelation
теперь кэшируются на экземпляреModel
, которому они принадлежат. Это изменение было отменено в версии Django 4.1.2.. DiscoverRunner
теперь возвращает ненулевой код ошибки при неожиданных успехах в тестах, помеченных какunittest.expectedFailure()
.CsrfViewMiddleware
больше не маскирует CSRF cookie, как это делает CSRF токен в DOM.CsrfViewMiddleware
теперь используетrequest.META['CSRF_COOKIE']
для хранения незамаскированного CSRF-секрета, а не замаскированной версии. Это недокументированный, частный API.- Атрибуты
ModelAdmin.actions
иinlines
теперь по умолчанию используют пустой кортеж, а не пустой список, чтобы предотвратить непреднамеренную мутацию. - Атрибут
type="text/css"
больше не включается в теги<link>
для CSS form media. - События JavaScript
formset:added
иformset:removed
теперь являются событиями чистого JavaScript и не зависят от jQuery. Более подробно об этом изменении смотрите События встроенной формы. - Аргумент
exc_info
недокументированной функцииdjango.utils.log.log_response()
заменяется наexception
. - Аргумент
size
недокументированной функцииdjango.views.static.was_modified_since()
удален. - В пользовательском интерфейсе выхода из системы администратора теперь используются запросы
POST
. - Недокументированное свойство
InlineAdminFormSet.non_form_errors
заменено методомnon_form_errors()
. Это соответствуетBaseFormSet
. - Согласно above, загрузчик кэшированных шаблонов теперь включен в разработке. Вы можете указать
OPTIONS['loaders']
, чтобы отменить это, если необходимо. - Недокументированный миксин
django.contrib.auth.views.SuccessURLAllowedHostsMixin
заменен наRedirectURLMixin
. - Подклассы
BaseConstraint
должны реализовать методvalidate()
, чтобы эти ограничения можно было использовать для проверки. - Недокументированные
URLResolver._is_callback()
,URLResolver._callback_strs
иURLPattern.lookup_str()
перемещены вdjango.contrib.admindocs.utils
. - Метод
Model.full_clean()
теперь преобразует значениеexclude
вset
. Также предпочтительнее передавать значениеexclude
в видеset
методамModel.clean_fields()
,Model.full_clean()
,Model.validate_unique()
иModel.validate_constraints()
. - Минимальная поддерживаемая версия
asgiref
увеличена с 3.4.1 до 3.5.2. - Комбинированные выражения больше не используют опасное для ошибок поведение угадывания
output_field
при совпадении типов аргументов. Как следствие, разрешениеoutput_field
для функций базы данных и комбинированных выражений теперь может привести к сбою при смешанных типах. В таких случаях необходимо явно задатьoutput_field
. - Команда
makemessages
больше не изменяет файлы.po
при обновлении. В старых версиях командаPOT-Creation-Date
всегда обновлялась.
Функции, устаревшие в версии 4.1¶
Выход из системы через GET¶
Выход из системы через GET
запросы к built-in logout view
устарел. Вместо этого используйте запросы POST
.
Если вы хотите сохранить удобство использования HTML-ссылки, вы можете использовать форму, которая будет выглядеть как ссылка:
<form id="logout-form" method="post" action="{% url 'admin:logout' %}">
{% csrf_token %}
<button type="submit">{% translate "Log out" %}</button>
</form>
#logout-form {
display: inline;
}
#logout-form button {
background: none;
border: none;
cursor: pointer;
padding: 0;
text-decoration: underline;
}
Разное¶
Контекст для шаблонов индексов sitemap, представляющий собой плоский список URL-адресов, устарел. Пользовательские шаблоны индекса sitemap должны быть обновлены для настроенного context variables, ожидая список объектов с
location
и необязательными атрибутамиlastmod
.Переходная установка
CSRF_COOKIE_MASKED
устарела.Аргумент
name
вdjango.utils.functional.cached_property()
является устаревшим, так как начиная с Python 3.6 в нем нет необходимости.Аргумент
opclasses
вdjango.contrib.postgres.constraints.ExclusionConstraint
устарел в пользу использованияOpClass()
вExclusionConstraint.expressions
. Чтобы использовать его, вам нужно добавить'django.contrib.postgres'
в вашINSTALLED_APPS
.После внесения этого изменения
makemigrations
создаст новую миграцию с двумя операциями:RemoveConstraint
иAddConstraint
. Поскольку это изменение не влияет на схему базы данных, операциюSeparateDatabaseAndState
можно использовать только для обновления состояния миграции без выполнения какого-либо SQL. Переместите сгенерированные операции в аргументstate_operations
вSeparateDatabaseAndState
. Например:class Migration(migrations.Migration): ... operations = [ migrations.SeparateDatabaseAndState( database_operations=[], state_operations=[ migrations.RemoveConstraint(...), migrations.AddConstraint(...), ], ), ]
Недокументированная возможность передачи
errors=None
вSimpleTestCase.assertFormError()
иassertFormsetError()
устарела. Вместо этого используйтеerrors=[]
.django.contrib.sessions.serializers.PickleSerializer
является устаревшим из-за риска удаленного выполнения кода.Использование
QuerySet.iterator()
в наборе запросов, который выполняет предварительную выборку связанных объектов без предоставления аргументаchunk_size
, устарело. В старых версиях предварительная выборка не производилась. Предоставление значения дляchunk_size
означает, что дополнительный запрос на чанк, необходимый для предварительной выборки, желателен.Передача несохраненных экземпляров модели в связанные фильтры устарела. В Django 5.0 будет возникать исключение.
created=True
добавляется к сигнатуреRemoteUserBackend.configure_user()
. Поддержка подклассовRemoteUserBackend
, которые не принимают этот аргумент, устарела.Псевдоним
django.utils.timezone.utc
дляdatetime.timezone.utc
устарел. Используйтеdatetime.timezone.utc
напрямую.Передача объекта ответа и имени формы/формсета в
SimpleTestCase.assertFormError()
иassertFormsetError()
устарела. Используйте:assertFormError(response.context["form_name"], ...) assertFormsetError(response.context["formset_name"], ...)
или передать объект формы/formset напрямую.
Недокументированный
django.contrib.gis.admin.OpenLayersWidget
является устаревшим.django.contrib.auth.hashers.CryptPasswordHasher
устарел.Возможность передавать
nulls_first=False
илиnulls_last=False
в методыExpression.asc()
иExpression.desc()
, а также выражениеOrderBy
является устаревшей. Вместо этого используйтеNone
.Шаблоны
"django/forms/default.html"
и"django/forms/formsets/default.html"
, которые являются прокси для шаблонов на основе таблиц, устарели. Вместо них используйте конкретный шаблон.Недокументированный метод
LogoutView.get_next_page()
переименован вget_success_url()
.
Функции, удаленные в 4.1¶
Эти функции достигли конца своего цикла устаревания и будут удалены в Django 4.1.
Подробнее об этих изменениях, в том числе о том, как удалить использование этих функций, смотрите Функции, устаревшие в версии 3.2.
- Устранена поддержка присвоения объектов, не поддерживающих создание глубоких копий с помощью
copy.deepcopy()
, атрибутам класса вTestCase.setUpTestData()
. - Устранена поддержка использования булевого значения в
BaseCommand.requires_system_checks
. - Аргумент
whitelist
и атрибутdomain_whitelist
вdjango.core.validators.EmailValidator
удаляются. - Переменная конфигурации приложения
default_app_config
удалена. TransactionTestCase.assertQuerysetEqual()
больше не вызываетrepr()
на queryset при сравнении со строковыми значениями.- Бэкенд
django.core.cache.backends.memcached.MemcachedCache
удален. - Убрана поддержка формата сообщений, существовавшего до версии Django 3.2 и использовавшегося
django.contrib.messages.storage.cookie.CookieStorage
.