• 3.1
  • 3.2
  • 5.0
  • Версия документации: 6.1

Примечания к выпуску Django 4.2

3 апреля 2023 г.

Добро пожаловать в Джанго 4.2!

Эти примечания к выпуску охватывают новые функции, а также некоторые обратно несовместимые изменения, о которых вам следует знать при обновлении с Django 4.1 или более ранней версии. Мы начали процесс прекращения поддержки некоторых функций.

См. руководство Обновление Django до новой версии, если вы обновляете существующий проект.

Django 4.2 обозначен как выпуск с долгосрочной поддержкой. Он будет получать обновления безопасности в течение как минимум трех лет после выпуска. Поддержка предыдущей LTS, Django 3.2, закончится в апреле 2024 года.

Совместимость версий Python

Django 4.2 поддерживает Python 3.8, 3.9, 3.10, 3.11 и 3.12 (начиная с версии 4.2.8). Мы настоятельно рекомендуем и официально поддерживаем только последнюю версию каждой серии.

Что нового в Джанго 4.2

Поддержка Псикопг 3

Django теперь поддерживает psycopg версии 3.1.8 или выше. Чтобы обновить код, установите библиотеку psycopg, вам не нужно менять ENGINE, поскольку django.db.backends.postgresql поддерживает обе библиотеки.

Поддержка psycopg2, скорее всего, будет прекращена и прекращена в какой-то момент в будущем.

Имейте в виду, что в psycopg 3 внесены некоторые критические изменения по сравнению с psycopg2. Как следствие, вам может потребоваться внести некоторые изменения, чтобы учесть отличия от psycopg2.

Комментарии к столбцам и таблицам

Новые параметры Field.db_comment и Meta.db_table_comment позволяют создавать комментарии к столбцам и таблицам соответственно. Например:

from django.db import models


class Question(models.Model):
    text = models.TextField(db_comment="Poll question")
    pub_date = models.DateTimeField(
        db_comment="Date and time when the question was published",
    )

    class Meta:
        db_table_comment = "Poll questions"


class Answer(models.Model):
    question = models.ForeignKey(
        Question,
        on_delete=models.CASCADE,
        db_comment="Reference to a question",
    )
    answer = models.TextField(db_comment="Question answer")

    class Meta:
        db_table_comment = "Question answers"

Кроме того, новая операция AlterModelTableComment позволяет изменять комментарии к таблице, определенные в Meta.db_table_comment.

Устранение последствий атаки BREACH

GZipMiddleware теперь включает средства защиты от атаки BREACH. Он добавит до 100 случайных байтов к ответам gzip, чтобы усложнить атаки BREACH. Подробнее о методе смягчения последствий читайте в статье «Исцеление нарушения (HTB)»_.

Хранение файлов в памяти

Новый класс django.core.files.storage.InMemoryStorage предоставляет непостоянное хранилище, полезное для ускорения тестов за счет предотвращения доступа к диску.

Пользовательские файловые хранилища

Новый параметр STORAGES позволяет настроить несколько пользовательских хранилищ файлов. Он также управляет механизмами хранения для управления файлами (ключ "default") и статическими файлами (ключ "staticfiles").

Старые настройки DEFAULT_FILE_STORAGE и STATICFILES_STORAGE устарели с этого выпуска.

Минорные изменения

django.contrib.admin

  • Светлую или темную цветовую тему администратора теперь можно переключать в пользовательском интерфейсе, а также настроить в соответствии с системными настройками.

  • Стек шрифтов администратора теперь отдает предпочтение шрифтам системного пользовательского интерфейса и больше не требует загрузки шрифтов. Кроме того, доступны переменные CSS, позволяющие более легко переопределить семейства шрифтов по умолчанию.

  • Шаблон admin/delete_confirmation.html теперь имеет несколько дополнительных блоков и скриптовых ловушек для упрощения настройки.

  • Выбранные параметры виджетов filter_horizontal и filter_vertical теперь можно фильтровать.

  • В шаблоне admin/base.html теперь есть новый блок nav-breadcrumbs, который содержит навигационный ориентир и блок breadcrumbs.

  • ModelAdmin.list_editable теперь использует атомарные транзакции при внесении изменений.

  • jQuery обновлен с версии 3.6.0 до 3.6.4.

django.contrib.auth

  • Число итераций по умолчанию для хэшера паролей PBKDF2 увеличено с 390 000 до 600 000.

  • UserCreationForm теперь сохраняет поля формы «многие ко многим» для пользовательской модели пользователя.

  • Новый BaseUserCreationForm теперь является рекомендуемым базовым классом для настройки формы создания пользователя.

django.contrib.gis

  • Сериализатор GeoJSON теперь выводит ключ id для сериализованных объектов, который по умолчанию равен первичному ключу объектов.

  • Класс GDALRaster теперь поддерживает pathlib.Path.

  • Класс GeoIP2 теперь поддерживает файлы .mmdb, загруженные с DB-IP.

  • Виджет шаблона OpenLayers больше не включает встроенный CSS (который также удаляет прежний блок «map_css»), чтобы лучше соответствовать строгой Политике безопасности контента.

  • OpenLayersWidget теперь основан на OpenLayers 7.2.2 (ранее 4.6.5).

  • Новый поиск isempty и выражение IsEmpty() позволяют фильтровать пустые геометрии в PostGIS.

  • Новые функции FromWKB() и FromWKT() позволяют создавать геометрии из общеизвестных двоичных (WKB) и общеизвестных текстовых (WKT) представлений.

django.contrib.postgres

django.contrib.sitemaps

  • Новый метод Sitemap.get_languages_for_item() позволяет настроить список языков, для которых отображается элемент.

django.contrib.staticfiles

  • ManifestStaticFilesStorage теперь имеет экспериментальную поддержку замены путей к модулям JavaScript в операторах import и export их хешированными аналогами. Если вы хотите попробовать, создайте подкласс ManifestStaticFilesStorage и установите для атрибута support_js_module_import_aggregation значение True.

  • Новый атрибут ManifestStaticFilesStorage.manifest_hash обеспечивает хэш всех файлов в манифесте и изменяется при каждом изменении одного из файлов.

Серверные базы данных

Отчеты об ошибках

Формы

  • ModelForm теперь принимает новую Meta опцию formfield_callback для настройки полей формы.

  • modelform_factory() теперь учитывает атрибут formfield_callback Meta формы.

Интернационализация

  • Добавлена ​​поддержка и переводы на центрально-курдский (сорани) язык.

Ведение журнала

  • Регистратор django.db.backends теперь регистрирует запросы управления транзакциями (BEGIN, COMMIT и ROLLBACK) на уровне DEBUG.

Команды управления

  • makemessages команда теперь поддерживает локали с частными вложенными тегами, такими как nl_NL-x-informal.

  • Новая опция makemigrations --update объединяет изменения модели с последней миграцией и оптимизирует полученные операции.

Миграции

  • Миграции теперь поддерживают сериализацию объектов enum.Flag.

Модели

  • QuerySet теперь широко поддерживает фильтрацию по оконным функциям, за исключением дизъюнктивного поиска фильтров по оконным функциям при выполнении агрегирования.

  • prefetch_lated() теперь поддерживает объекты Prefetch с нарезанными наборами запросов.

  • Регистрация поисков в экземплярах Field теперь поддерживается.

  • Новый аргумент robust для on_commit() позволяет выполнять действия, которые могут завершиться неудачей после успешного подтверждения транзакции базы данных.

  • Новое выражение KT() представляет текстовое значение ключа, индекса или преобразования пути JSONField.

  • Now теперь поддерживает точность до микросекунд в MySQL и точность до миллисекунд в SQLite.

  • F() выражения, выводящие BooleanField, теперь можно инвертировать с помощью ~F() (оператор инверсии).

  • Model теперь предоставляет асинхронные версии некоторых методов, использующих базу данных, с использованием префикса a: adelete(), arefresh_from_db() и asave().

  • Связанные менеджеры теперь предоставляют асинхронные версии методов, которые изменяют набор связанных объектов, используя префикс a: aadd(), aclear(), aremove() и aset().

  • CharField.max_length больше не требуется устанавливать в PostgreSQL, который поддерживает неограниченное количество столбцов VARCHAR.

Запросы и ответы

  • StreamingHttpResponse теперь поддерживает асинхронные итераторы, когда Django обслуживается через ASGI.

Тесты

  • Опция test --debug-sql теперь форматирует SQL-запросы с помощью sqlparse.

  • Классы RequestFactory, AsyncRequestFactory, Client и AsyncClient теперь поддерживают параметр headers, который принимает словарь имен и значений заголовков. Это обеспечивает более естественный синтаксис объявления заголовков.

    # Before:
    self.client.get("/home/", HTTP_ACCEPT_LANGUAGE="fr")
    await self.async_client.get("/home/", ACCEPT_LANGUAGE="fr")
    
    # After:
    self.client.get("/home/", headers={"accept-language": "fr"})
    await self.async_client.get("/home/", headers={"accept-language": "fr"})
    

Утилиты

  • Новый параметр encoder для функции django.utils.html.json_script() позволяет настраивать класс кодировщика JSON.

  • Частная внутренняя копия urllib.parse.urlsplit() теперь удаляет '\r', '\n' и '\t' (см. CVE 2022-0391 и bpo-43882). Это сделано для защиты проектов, которые могут неправильно использовать внутреннюю функцию url_has_allowed_host_and_scheme() вместо использования одной из документированных функций для обработки перенаправления URL-адресов. Функции Django не были затронуты.

  • Новая функция django.utils.http.content_disposition_header() возвращает значение HTTP-заголовка Content-Disposition, как указано в RFC 6266.

Валидаторы

  • Список общих паролей, используемых CommonPasswordValidator, обновляется до самой последней версии.

Изменения обратной несовместимости в версии 4.2

Серверный API базы данных

В этом разделе описаны изменения, которые могут потребоваться в сторонних базах данных.

  • DatabaseFeatures.allows_group_by_pk удален, поскольку он остался только для размещения расширения MySQL, которое было заменено правильным обнаружением функциональных зависимостей в MySQL 5.7.15. Обратите внимание, что DatabaseFeatures.allows_group_by_selected_pks по-прежнему поддерживается и должен быть включен, если ваш сервер поддерживает обнаружение функциональных зависимостей в предложениях GROUP BY, как указано в стандарте SQL:1999.

  • inspectdb теперь использует display_size из DatabaseIntrospection.get_table_description() вместо internal_size для CharField.

Прекращена поддержка MariaDB 10.3.

Вышестоящая поддержка MariaDB 10.3 заканчивается в мае 2023 года. Django 4.2 поддерживает MariaDB 10.4 и выше.

Прекращена поддержка MySQL 5.7.

Поддержка MySQL 5.7 заканчивается в октябре 2023 года. Django 4.2 поддерживает MySQL 8 и выше.

Прекращена поддержка PostgreSQL 11.

Поддержка исходной версии PostgreSQL 11 заканчивается в ноябре 2023 года. Django 4.2 поддерживает PostgreSQL 12 и выше.

Теперь может потребоваться установка update_fields в Model.save().

Чтобы избежать обновления ненужных столбцов, QuerySet.update_or_create() теперь передает update_fields в вызовы Model.save(). Как следствие, любые поля, измененные в пользовательских методах save(), должны быть добавлены к аргументу ключевого слова update_fields перед вызовом super(). Дополнительную информацию см. в разделе Переопределение методов модели.

Прекращена поддержка необработанных агрегаций в MySQL.

MySQL 8+ допускает функциональные зависимости от столбцов GROUP BY, поэтому обходной путь, существовавший до Django 4.2, с группировкой по первичным ключам основной таблицы, удален. Как следствие, использование агрегатов RawSQL() больше не поддерживается в MySQL, поскольку нет способа определить, необходимы ли такие агрегаты или действительны ли они в предложении GROUP BY. Вместо этого используйте Функции агрегации.

Разнообразный

  • Недокументированная функция django.http.multipartparser.parse_header() удалена. Вместо этого используйте django.utils.http.parse_header_parameters().

  • {%blocktranslate asvar %} результат теперь помечен как безопасный для целей вывода (HTML).

  • HTML-атрибут autofocus в поле поиска администратора удален, так как он может сбивать с толку программы чтения с экрана.

  • Опция makemigrations --check больше не создает отсутствующие файлы миграции.

  • Аргумент alias для Expression.get_group_by_cols() удален.

  • Минимальная поддерживаемая версия sqlparse увеличена с 0.2.2 до 0.3.1.

  • Недокументированный параметр negated выражения Exists удален.

  • Аргумент is_summary недокументированного метода Query.add_annotation() удален.

  • Минимальная поддерживаемая версия SQLite увеличена с 3.9.0 до 3.21.0.

  • Минимальная поддерживаемая версия asgiref увеличена с 3.5.2 до 3.6.0.

  • UserCreationForm теперь отклоняет имена пользователей, которые отличаются только по регистру. Если вам нужно предыдущее поведение, используйте вместо него BaseUserCreationForm.

  • Минимальная поддерживаемая версия mysqlclient увеличена с 1.4.0 до 1.4.3.

  • Минимальная поддерживаемая версия argon2-cffi увеличена с 19.1.0 до 19.2.0.

  • Минимальная поддерживаемая версия Pillow увеличена с 6.2.0 до 6.2.1.

  • Минимальная поддерживаемая версия jinja2 увеличена с 2.9.2 до 2.11.0.

  • Минимальная поддерживаемая версия redis-py увеличена с 3.0.0 до 3.4.0.

  • Созданные вручную объекты WSGIRequest должны быть предоставлены в виде файлового объекта для wsgi.input. Раньше поведение Django было более мягким, чем ожидалось, как указано в спецификации WSGI.

  • Поддержка PROJ < 5 удалена.

  • EmailBackend теперь проверяет имя хоста и сертификаты. Если вам нужно предыдущее поведение, которое является менее ограничительным и не рекомендуется, создайте подкласс EmailBackend и переопределите свойство ssl_context.

Функции, устаревшие в версии 4.2

Опция index_together устарела в пользу indexes

Опция Meta.index_together устарела в пользу опции indexes.

Миграцию существующего index_together следует рассматривать как миграцию. Например:

class Author(models.Model):
    rank = models.IntegerField()
    name = models.CharField(max_length=30)

    class Meta:
        index_together = [["rank", "name"]]

Должно стать:

class Author(models.Model):
    rank = models.IntegerField()
    name = models.CharField(max_length=30)

    class Meta:
        indexes = [models.Index(fields=["rank", "name"])]

Запуск команды makemigrations создаст миграцию, содержащую операцию RenameIndex, которая переименует существующий индекс. Затем рассмотрите возможность сокращения миграций, чтобы удалить index_together из исторических миграций.

Операция миграции AlterIndexTogether теперь официально поддерживается только для файлов миграции до Django 4.2. По соображениям обратной совместимости он по-прежнему является частью общедоступного API, и его прекращение поддержки или удаление не планируется, но его не следует использовать для новых миграций. Вместо этого используйте операции AddIndex и RemoveIndex.

Передача закодированных строковых литералов JSON в JSONField устарела.

JSONField и связанные с ним поисковые запросы и агрегаты, используемые для передачи строковых литералов в кодировке JSON, что вызывало неоднозначность в отношении того, были ли строковые литералы уже закодированы с точки зрения серверной части базы данных.

В течение периода прекращения поддержки будут предприняты попытки декодирования строковых литералов в формате JSON, и в случае успеха будет выдано предупреждение, указывающее на передачу незакодированных форм.

Код, который использовался для передачи строковых литералов в кодировке JSON:

Document.objects.bulk_create(
    Document(data=Value("null")),
    Document(data=Value("[]")),
    Document(data=Value('"foo-bar"')),
)
Document.objects.annotate(
    JSONBAgg("field", default=Value("[]")),
)

Должно стать:

Document.objects.bulk_create(
    Document(data=Value(None, JSONField())),
    Document(data=[]),
    Document(data="foo-bar"),
)
Document.objects.annotate(
    JSONBAgg("field", default=[]),
)

В Django 5.1+ строковые литералы будут неявно интерпретироваться как строковые литералы JSON.

Разнообразный

  • Метод BaseUserManager.make_random_password() устарел. См. рецепты и лучшие практики для использования модуля Python secrets для генерации паролей.

  • Фильтр шаблона length_is устарел в пользу length и оператора == в теге {% if %}. Например

    {% if value|length == 4 %}{% endif %}
    {% if value|length == 4 %}True{% else %}False{% endif %}
    

    вместо:

    {% if value|length_is:4 %}{% endif %}
    {{ value|length_is:4 }}
    
  • django.contrib.auth.hashers.SHA1PasswordHasher, django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher и django.contrib.auth.hashers.UnsaltedMD5PasswordHasher устарели.

  • django.contrib.postgres.fields.CICharField устарел в пользу CharField(db_collation="…") с недетерминированными параметрами сортировки, нечувствительными к регистру.

  • django.contrib.postgres.fields.CIEmailField устарел в пользу EmailField(db_collation="…") с недетерминированной сортировкой без учета регистра.

  • django.contrib.postgres.fields.CITextField устарел в пользу TextField(db_collation="…") с недетерминированными параметрами сортировки, нечувствительными к регистру.

  • Миксин django.contrib.postgres.fields.CIText устарел.

  • Атрибуты map_height и map_width в BaseGeometryWidget устарели, вместо этого используйте CSS для определения размера виджетов карты.

  • SimpleTestCase.assertFormsetError() устарел в пользу assertFormSetError().

  • TransactionTestCase.assertQuerysetEqual() устарел в пользу assertQuerySetEqual().

  • Передача позиционных аргументов в Signer и TimestampSigner устарела в пользу аргументов, содержащих только ключевые слова.

  • Параметр DEFAULT_FILE_STORAGE устарел в пользу STORAGES["default"].

  • Параметр STATICFILES_STORAGE устарел в пользу STORAGES["staticfiles"].

  • Функция django.core.files.storage.get_storage_class() устарела.

Back to Top