Примечания к выпуску Django 4.1¶
3 августа 2022 г.
Добро пожаловать в Джанго 4.1!
Эти примечания к выпуску охватывают новые функции, а также некоторые обратно несовместимые изменения, о которых вам следует знать при обновлении с Django 4.0 или более ранней версии. Мы начали процесс прекращения поддержки некоторых функций.
См. руководство Обновление Django до новой версии, если вы обновляете существующий проект.
Совместимость версий Python¶
Django 4.1 поддерживает Python 3.8, 3.9, 3.10 и 3.11 (начиная с версии 4.1.3). Мы настоятельно рекомендуем и официально поддерживаем только последнюю версию каждой серии.
Что нового в Джанго 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 и интеграцией асинхронных драйверов базы данных. Новый интерфейс асинхронного набора запросов в настоящее время инкапсулирует необходимые операции sync_to_async() и позволит вашему коду использовать преимущества асинхронной поддержки ORM по мере ее развития.
Подробности и ограничения см. в разделе Асинхронные запросы.
Проверка ограничений¶
Проверьте, unique и exclusion ограничения, определенные в Meta.constraints Параметры теперь проверяются во время проверки модели.
Доступность рендеринга форм¶
Чтобы помочь пользователям с программами чтения с экрана и другими вспомогательными технологиями, в этом выпуске доступны новые шаблоны форм на основе <div>. Они обеспечивают более доступную навигацию, чем старые шаблоны, и позволяют правильно группировать связанные элементы управления, такие как списки радио, в наборы полей.
Рекомендуется использовать новые шаблоны, которые станут стилем рендеринга формы по умолчанию при выводе формы, например {{ form }} в шаблоне из Django 5.0.
Чтобы облегчить внедрение нового стиля вывода, шаблоны форм и наборов форм по умолчанию теперь можно настроить на уровне проекта с помощью параметра FORM_RENDERER.
Подробную информацию смотрите в разделе «Формы» (ниже)<forms-4.1>.
Минорные изменения¶
django.contrib.admin¶
Переменные CSS темного режима администратора <admin-theming> теперь применяются в отдельной таблице стилей и блоке шаблона.
Фильтры списка ModelAdmin, предоставляющий пользовательские подклассы
FieldListFilter, теперь могут управлять разделителем значений строки запроса при фильтрации нескольких значений с использованием поиска__in.Администраторское представление истории <django.contrib.admin.ModelAdmin.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(). Пользовательские шаблоны индексов карты сайта должны быть обновлены для скорректированных контекстных переменных.
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теперь является свойством, передаваемым средству визуализации, но его можно переопределить строковым значением, чтобы указать имя шаблона для каждого класса формы.Аналогично, шаблон по умолчанию, используемый для рендеринга наборов форм, может быть указан через соответствующий атрибут рендерера
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>с помощью нового аргументаtaglabel_tag().Новый аргумент edit_only для
modelformset_factory()иinlineformset_factory()позволяет предотвратить создание новых объектов.Атрибуты класса
jsиcssMedia теперь позволяют использовать хэшируемые объекты, а не только строки пути, если эти объекты реализуют метод__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позволяет включить проверки работоспособности постоянных подключений к базе данных, чтобы уменьшить количество неудачных запросов, например после перезапуска сервера базы данных.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теперь отправляютисточникудаления.
Шаблоны¶
Атрибут id элемента HTML
<script>больше не требуется при упаковке фильтра шаблонаjson_script.кэшированный загрузчик шаблоновтеперь включен в разработке, когдаDEBUGимеет значениеTrueиOPTIONS['loaders']не указан. При необходимости вы можете указатьOPTIONS['loaders'], чтобы переопределить это.
Тесты¶
DiscoverRunnerтеперь поддерживает параллельный запуск тестов в macOS, Windows и любых других системах, где методом запускаmultiprocessingпо умолчанию являетсяspawn.Вложенный атомарный блок, помеченный как устойчивый в
django.test.TestCase, теперь вызывает ошибкуRuntimeError, так же, как и вне тестов.SimpleTestCase.assertFormError()иassertFormsetError()теперь поддерживают прямую передачу объекта формы/набора форм.
URL-адреса¶
Новый атрибут
ResolverMatch.captured_kwargsхранит захваченные аргументы ключевого слова, полученные из URL-адреса.Новый атрибут
ResolverMatch.extra_kwargsхранит дополнительные аргументы ключевого слова, передаваемые функции просмотра.
Утилиты¶
SimpleLazyObjectтеперь поддерживает операции сложения.mark_safe()теперь сохраняет ленивые объекты.
Валидаторы¶
Новый
StepValueValidatorпроверяет, является ли значение целым кратным заданному размеру шага. Этот новый валидатор используется для нового аргумента «step_size», добавленного для формирования полей, представляющих числовые значения.
Изменения обратной несовместимости в версии 4.1¶
Серверный API базы данных¶
В этом разделе описаны изменения, которые могут потребоваться в сторонних базах данных.
BaseDatabaseFeatures.has_case_insensitivity_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и возвращают 2-кортеж, содержащий некоторый 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'], а пользователь ищет 'Джамал 17', родительские строки будут возвращены только в том случае, если существует связь с некоторым 17-летним ребенком по имени Джамал, а не возвращаются также родители, у которых просто есть младший или старший ребенок по имени Джамал в дополнение к какому-то другому 17-летнему ребенку.
Дополнительную информацию об этой разнице можно найти в теме Фильтрация по связям многие-ко-многим. В Django 4.0 и более ранних версиях get_search_results() следовал второму примеру запроса, но это недокументированное поведение приводило к запросам с чрезмерным количеством соединений.
Отменить изменения внешнего ключа для несохраненных экземпляров модели.¶
Чтобы унифицировать поведение с отношениями «многие ко многим» для несохраненных экземпляров модели, обратный внешний ключ теперь вызывает ValueError при вызове связанных менеджеров для несохраненных объектов.
Разнообразный¶
Связанные менеджеры для
ForeignKey,ManyToManyFieldиGenericRelationтеперь кэшируются в экземпляреModel, которому они принадлежат. Это изменение было отменено в Django 4.1.2.DiscoverRunnerтеперь возвращает ненулевой код ошибки при неожиданных успехах тестов, отмеченныхunittest.expectedFailure().CsrfViewMiddlewareбольше не маскирует файл cookie CSRF, как это делает токен 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() заменяется на исключение.
Аргумент 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 к встроенному представлению выхода из системы устарел. Вместо этого используйте запросы 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;
}
Разнообразный¶
Контекст для шаблонов индекса карты сайта в виде плоского списка URL-адресов устарел. Пользовательские шаблоны индексов карты сайта должны быть обновлены для скорректированных контекстных переменных, ожидая список объектов с
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_operationsSeparateDatabaseAndState. Например: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"], ...)
или вместо этого передайте объект формы/набора форм напрямую.
Недокументированный django.contrib.gis.admin.OpenLayersWidget устарел.
django.contrib.auth.hashers.CryptPasswordHasherустарел.Возможность передавать nulls_first=False или nulls_last=False в методы Expression.asc() и Expression.desc(), а выражение OrderBy считается устаревшим. Вместо этого используйте «Нет».
Шаблоны
"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()для набора запросов по сравнению со строковыми значениями.Серверная часть django.core.cache.backends.memcached.MemcachedCache удалена.
Поддержка формата сообщений до Django 3.2, используемого django.contrib.messages.storage.cookie.CookieStorage, удалена.