Django 4.1 release notes¶
August 3, 2022
Добро пожаловать в Django 4.1!
Эти заметки о выпуске охватывают new features, а также некоторые backwards incompatible changes, о которых вы должны знать при переходе с Django 4.0 или более ранней версии. Мы begun the deprecation process for some features.
См. руководство How to upgrade Django to a newer version, если вы обновляете существующий проект.
Совместимость с Python¶
Django 4.1 supports Python 3.8, 3.9, 3.10, and 3.11 (as of 4.1.3). We highly recommend and only officially support the latest release of each series.
Что нового в 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!")
Более подробную информацию см. в разделе Asynchronous class-based views.
Асинхронный интерфейс 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 cookie, как это делает CSRF token в DOM. Если вы обновляете несколько экземпляров одного и того же проекта до Django 4.1, вам следует установить CSRF_COOKIE_MASKED на True во время перехода, чтобы обеспечить совместимость со старыми версиями Django. После завершения перехода на 4.1 вы можете перестать переопределять CSRF_COOKIE_MASKED.
This setting is deprecated as of this release and will be removed in 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позволяет задавать границы для списков и кортежей. ExclusionConstraintnow allows specifying operator classes with theOpClass()expression.
django.contrib.sitemaps¶
- Шаблон индекса карты сайта по умолчанию
<sitemapindex>теперь включает метку времени<lastmod>там, где она доступна, с помощью нового методаget_latest_lastmod(). Пользовательские шаблоны индекса sitemap должны быть обновлены для корректировки context variables.
django.contrib.staticfiles¶
ManifestStaticFilesStorageтеперь заменяет пути к ссылкам на карту источников CSS их хэшированными аналогами.
Database backends¶
- Бэкенды баз данных сторонних производителей теперь могут указывать минимально необходимую версию базы данных с помощью атрибута
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()позволяет предотвратить создание новых объектов.T
Новые атрибуты
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 и любых других системах, где по умолчанию используется метод запускаmultiprocessingspawn.- Вложенный атомарный блок, помеченный как долговечный в
django.test.TestCase, теперь вызываетRuntimeError, как и вне тестов. SimpleTestCase.assertFormError()andassertFormsetError()now support passing a form/formset object directly.
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.
Dropped support for PostgreSQL 10¶
Upstream support for PostgreSQL 10 ends in November 2022. Django 4.1 supports PostgreSQL 11 and higher.
Прекращена поддержка 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 для несохраненных объектов.
Разное¶
- Related managers for
ForeignKey,ManyToManyField, andGenericRelationare now cached on theModelinstance to which they belong. This change was reverted in Django 4.1.2. - Бегунок тестирования Django теперь возвращает ненулевой код ошибки при неожиданных успехах тестов, помеченных
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.
Функции, устаревшие в версии 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( ... ), ], ), ]
The undocumented ability to pass
errors=NonetoSimpleTestCase.assertFormError()andassertFormsetError()is deprecated. Useerrors=[]instead.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.