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

Декабрь 2, 2019

Добро пожаловать в Django 3.0!

Эти заметки о выпуске охватывают new features, а также некоторые backwards incompatible changes, о которых вы захотите знать при переходе с Django 2.2 или более ранней версии. Мы dropped some features, которые достигли конца своего цикла устаревания, и мы begun the deprecation process for some features.

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

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

Django 3.0 поддерживает Python 3.6, 3.7, 3.8 и 3.9 (начиная с версии 3.0.11). Мы настоятельно рекомендуем и официально поддерживаем только последний выпуск каждой серии.

Серия Django 2.2.x является последней, поддерживающей Python 3.5.

Поддержка сторонних библиотек для старых версий Django

После выхода Django 3.0 мы предлагаем авторам сторонних приложений отказаться от поддержки всех версий Django, предшествующих 2.2. В это время вы должны иметь возможность запускать тесты вашего пакета, используя python -Wd, чтобы появились предупреждения об устаревании. После исправления предупреждений об износе ваше приложение должно быть совместимо с Django 3.0.

Что нового в Django 3.0

Поддержка MariaDB

Django теперь официально поддерживает MariaDB 10.1 и выше. Более подробную информацию смотрите в MariaDB notes.

Поддержка ASGI

Django 3.0 начинает наш путь к тому, чтобы сделать Django полностью async-совместимым, предоставляя поддержку запуска в качестве приложения ASGI.

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

На данном этапе поддержка async применяется только к внешнему приложению ASGI. Внутри все остается синхронным. Асинхронное промежуточное ПО, представления и т.д. пока не поддерживаются. Тем не менее, вы можете использовать ASGI промежуточное ПО вокруг приложения Django, что позволит вам комбинировать Django с другими ASGI-фреймворками.

Нет необходимости переключать свои приложения, если вы не хотите начать экспериментировать с асинхронным кодом, но у нас есть documentation on deploying with ASGI, если вы хотите узнать больше.

Обратите внимание, что в качестве побочного эффекта этого изменения Django теперь знает об асинхронных циклах событий и будет блокировать вызов кода, помеченного как «async unsafe» - например, операций ORM - из асинхронного контекста. Если вы раньше использовали Django из асинхронного кода, это может сработать, если вы делали это неправильно. Если вы видите ошибку SynchronousOnlyOperation, то внимательно изучите свой код и переместите все операции с базой данных в синхронный дочерний поток.

Ограничения исключения в PostgreSQL

Новый класс ExclusionConstraint позволяет добавлять ограничения исключения в PostgreSQL. Ограничения добавляются в модели с помощью опции Meta.constraints.

Фильтр выражений

Выражения, выводящие BooleanField, теперь можно использовать непосредственно в фильтрах QuerySet, без необходимости сначала аннотировать, а затем фильтровать по аннотации.

Перечисления для выбора поля модели

Пользовательские типы перечислений TextChoices, IntegerChoices и Choices теперь доступны как способ определения Field.choices. Типы TextChoices и IntegerChoices предусмотрены для текстовых и целочисленных полей. Класс Choices позволяет определить совместимое перечисление для других конкретных типов данных. Эти пользовательские типы перечислений поддерживают человекочитаемые метки, которые могут быть переведены и доступны через свойство перечисления или его членов. Более подробную информацию и примеры смотрите в Enumeration types.

Незначительные особенности

django.contrib.admin

  • Добавлена поддержка атрибута admin_order_field для свойств в ModelAdmin.list_display.
  • Новый метод ModelAdmin.get_inlines() позволяет указывать инлайны на основе запроса или экземпляра модели.
  • Библиотека Select2 обновлена с версии 4.0.3 до 4.0.7.
  • jQuery обновлен с версии 3.3.1 до 3.4.1.

django.contrib.auth

  • Новый атрибут reset_url_token в PasswordResetConfirmView позволяет указать параметр токена, отображаемый как компонент URL-адресов сброса пароля.
  • Добавлен класс BaseBackend для облегчения настройки бэкендов аутентификации.
  • Добавлен метод get_user_permissions(), зеркально отражающий существующий метод get_group_permissions().
  • Добавлен HTML атрибут autocomplete к виджетам полей имени пользователя, электронной почты и пароля в django.contrib.auth.forms для лучшего взаимодействия с менеджерами паролей в браузере.
  • createsuperuser теперь возвращается к переменным окружения для пароля и обязательных полей, когда соответствующий аргумент командной строки не предоставлен в неинтерактивном режиме.
  • REQUIRED_FIELDS теперь поддерживает ManyToManyFields.
  • Новый метод UserManager.with_perm() возвращает пользователей, имеющих указанное разрешение.
  • Количество итераций по умолчанию для хешера паролей PBKDF2 увеличено со 150 000 до 180 000.

django.contrib.gis

  • Позволяет функциям пространственного поиска MySQL работать с реальной геометрией. Предыдущая поддержка была ограничена ограничивающими рамками.
  • Добавлена функция GeometryDistance, поддерживаемая в PostGIS.
  • Добавлена поддержка блока furlong в Distance.
  • Настройка GEOIP_PATH теперь поддерживает pathlib.Path.
  • Класс GeoIP2 теперь принимает pathlib.Path path.

django.contrib.postgres

  • Новый RangeOperators помогает избежать опечаток в операторах SQL, которые могут использоваться вместе с RangeField.
  • Новое выражение RangeBoundary представляет границы диапазона.
  • Новые классы AddIndexConcurrently и RemoveIndexConcurrently позволяют создавать и удалять индексы CONCURRENTLY на PostgreSQL.

django.contrib.sessions

  • Новый метод get_session_cookie_age() позволяет динамически указывать возраст куки сессии.

django.contrib.syndication

Кэш

Хранение файлов

  • Новый метод Storage.get_alternative_name() позволяет настроить алгоритм генерации имен файлов, если файл с загружаемым именем уже существует.

Формы

  • Наборы форм могут управлять виджетом, используемым при заказе форм через can_order, устанавливая атрибут ordering_widget или переопределяя get_ordering_widget().

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

  • Добавлены параметры LANGUAGE_COOKIE_HTTPONLY, LANGUAGE_COOKIE_SAMESITE и LANGUAGE_COOKIE_SECURE для установки флагов HttpOnly, SameSite и Secure для языковых файлов cookie. Значения по умолчанию этих параметров сохраняют предыдущее поведение.
  • Добавлена поддержка и переводы для узбекского языка.

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

  • Новый параметр reporter_class в AdminEmailHandler позволяет подклассу django.views.debug.ExceptionReporter настроить текст трассировки, отправляемый на сайт ADMINS, когда DEBUG становится False.

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

  • Новая опция compilemessages --ignore позволяет игнорировать определенные каталоги при поиске .po файлов для компиляции.
  • showmigrations --list теперь показывает применяемые времена дат, когда --verbosity имеет значение 2 и выше.
  • В PostgreSQL dbshell теперь поддерживает сертификаты TLS на стороне клиента.
  • inspectdb теперь интроспекция OneToOneField, когда внешний ключ имеет ограничение уникального или первичного ключа.
  • Новая опция --skip-checks пропускает проверку системы перед выполнением команды.
  • Опции startapp --template и startproject --template теперь поддерживают шаблоны, хранящиеся в архивах XZ (.tar.xz, .txz) и LZMA (.tar.lzma, .tlz).

Модели

  • Добавлены функции хэш-базы данных MD5, SHA1, SHA224, SHA256, SHA384 и SHA512.

  • Добавлена функция базы данных Sign.

  • Новый параметр is_dst функций базы данных Trunc определяет обработку несуществующих и неоднозначных дат.

  • connection.queries теперь показывает COPY TO утверждения на PostgreSQL.

  • FilePathField теперь принимает вызов для path.

  • Разрешенная симметричная промежуточная таблица для самореферентного ManyToManyField.

  • Атрибуты name CheckConstraint, UniqueConstraint и Index теперь поддерживают интерполяцию метки приложения и класса с помощью держателей '%(app_label)s' и '%(class)s'.

  • Новый атрибут Field.descriptor_class позволяет полям модели настраивать поведение get и set, переопределяя их descriptors.

  • Avg и Sum теперь поддерживают аргумент distinct.

  • Добавлено SmallAutoField, которое действует подобно AutoField, за исключением того, что оно допускает только значения ниже определенного (зависящего от базы данных) предела. Значения от 1 до 32767 безопасны во всех базах данных, поддерживаемых Django.

  • AutoField, BigAutoField и SmallAutoField теперь наследуются от IntegerField, BigIntegerField и SmallIntegerField соответственно. Системные проверки и валидаторы теперь также правильно наследуются.

  • FileField.upload_to теперь поддерживает pathlib.Path.

  • CheckConstraint теперь поддерживается на MySQL 8.0.16+.

  • Новый метод allows_group_by_selected_pks_on_model() в django.db.backends.base.BaseDatabaseFeatures позволяет оптимизировать условия GROUP BY, чтобы требовать только первичные ключи выбранных моделей. По умолчанию он поддерживается только для управляемых моделей на PostgreSQL.

    Чтобы включить оптимизацию GROUP BY только по первичному ключу для неуправляемых моделей, необходимо подкласс движка базы данных PostgreSQL, переопределив метод features class allows_group_by_selected_pks_on_model() так, как вам нужно. Пример смотрите в Subclassing the built-in database backends.

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

  • Позволяет инициализировать HttpResponse содержимым memoryview.
  • Для использования, например, в шаблонах Django, HttpRequest.headers теперь позволяет искать с использованием подчеркивания (например, user_agent) вместо дефиса.

Безопасность

  • X_FRAME_OPTIONS теперь имеет значение по умолчанию 'DENY'. В старых версиях параметр X_FRAME_OPTIONS по умолчанию имеет значение 'SAMEORIGIN'. Если ваш сайт использует собственные фреймы, вам необходимо явно установить X_FRAME_OPTIONS = 'SAMEORIGIN', чтобы они продолжали работать.
  • SECURE_CONTENT_TYPE_NOSNIFF теперь имеет значение по умолчанию True. Если это включено, SecurityMiddleware устанавливает заголовок X-Content-Type-Options: nosniff во всех ответах, которые еще не имеют его.
  • SecurityMiddleware теперь может отправить заголовок Referrer-Policy.

Тесты

  • Новый аргумент теста Client raise_request_exception позволяет контролировать, должны ли исключения, поднятые во время запроса, также подниматься в тесте. Значение по умолчанию True для обратной совместимости. Если значение False и происходит исключение, клиент теста возвращает ответ 500 с атрибутом exc_info, кортеж, содержащий информацию о произошедшем исключении.
  • Тесты и тестовые случаи для запуска можно выбирать по шаблону имени теста с помощью новой опции test -k.
  • Сравнение HTML, используемое assertHTMLEqual(), теперь рассматривает текст, ссылки на символы и ссылки на сущности, которые ссылаются на один и тот же символ, как эквивалентные.
  • Django test runner теперь поддерживает режим headless для тестов selenium на поддерживаемых браузерах. Добавьте опцию --headless для включения этого режима.
  • Django test runner теперь поддерживает опции --start-at и --start-after для запуска тестов, начиная с определенного модуля верхнего уровня.
  • Бегунок тестирования Django теперь поддерживает опцию --pdb для порождения отладчика при каждой ошибке или сбое.

Изменения в версии 3.0, несовместимые с обратными изменениями

Model.save() при предоставлении значения по умолчанию для первичного ключа

Model.save() больше не пытается найти строку при сохранении нового экземпляра Model, если для первичного ключа задано значение по умолчанию, и всегда выполняет один запрос INSERT. В старых версиях Django Model.save() выполнял либо INSERT, либо UPDATE в зависимости от того, существует ли строка или нет.

Это делает вызов Model.save() при предоставлении значения первичного ключа по умолчанию эквивалентным передаче force_insert=True в save() модели. Попытки использовать новый экземпляр Model для обновления существующей строки приведут к ошибке IntegrityError.

Чтобы обновить существующую модель для определенного значения первичного ключа, используйте метод update_or_create() или QuerySet.filter(pk=…).update(…). Например:

>>> MyModel.objects.update_or_create(pk=existing_pk, defaults={'name': 'new name'})
>>> MyModel.objects.filter(pk=existing_pk).update(name='new name')

API бэкенда базы данных

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

  • Вторым аргументом DatabaseIntrospection.get_geometry_type() теперь является описание строки, а не имя столбца.
  • DatabaseIntrospection.get_field_type() больше не может возвращать кортежи.
  • Если база данных может создавать внешние ключи в том же операторе SQL, который добавляет поле, добавьте SchemaEditor.sql_create_column_inline_fk с соответствующим SQL; в противном случае установите DatabaseFeatures.can_create_inline_fk = False.
  • DatabaseFeatures.can_return_id_from_insert и can_return_ids_from_bulk_insert переименованы в can_return_columns_from_insert и can_return_rows_from_bulk_insert.
  • Функции базы данных теперь обрабатывают формат datetime.timezone при создании с использованием экземпляров datetime.timedelta (например, timezone(timedelta(hours=5)), который выводил бы 'UTC+05:00'). Сторонние бэкенды должны обрабатывать этот формат при подготовке DateTimeField в datetime_cast_date_sql(), datetime_extract_sql() и т.д.
  • Записи для AutoField, BigAutoField и SmallAutoField добавлены в DatabaseOperations.integer_field_ranges для поддержки валидаторов целочисленного диапазона для этих типов полей. Сторонним бэкендам может потребоваться настройка записей по умолчанию.
  • DatabaseOperations.fetch_returned_insert_id() заменяется на fetch_returned_insert_columns(), который возвращает список значений, возвращаемых оператором INSERT RETURNING, вместо одного значения.
  • DatabaseOperations.return_insert_id() заменяется на return_insert_columns(), который принимает аргумент fields, представляющий собой итерацию полей, которые будут возвращены после вставки. Обычно это только автоматически генерируемый первичный ключ.

django.contrib.admin

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

django.contrib.gis

  • Удалена поддержка PostGIS 2.1.
  • Удалена поддержка SpatiaLite 4.1 и 4.2.
  • Удалена поддержка GDAL 1.11 и GEOS 3.4.

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

Поддержка PostgreSQL 9.4 заканчивается в декабре 2019 года. Django 3.0 поддерживает PostgreSQL 9.5 и выше.

Прекращена поддержка Oracle 12.1

Поддержка Oracle 12.1 заканчивается в июле 2021 года. Django 2.2 будет поддерживаться до апреля 2022 года. Django 3.0 официально поддерживает Oracle 12.2 и 18c.

Удалены частные API совместимости с Python 2

Хотя поддержка Python 2 была удалена в Django 2.0, некоторые частные API не были удалены из Django, чтобы сторонние приложения могли продолжать использовать их до окончания срока службы Python 2.

Поскольку мы ожидаем, что приложения откажутся от совместимости с Python 2 при добавлении поддержки Django 3.0, мы удаляем эти API на данный момент.

  • django.test.utils.str_prefix() - В Python 3 у строк нет префиксов „u“.
  • django.test.utils.patch_logger() - Вместо этого используйте unittest.TestCase.assertLogs().
  • django.utils.lru_cache.lru_cache() - Псевдоним functools.lru_cache().
  • django.utils.decorators.available_attrs() - Эта функция возвращает functools.WRAPPER_ASSIGNMENTS.
  • django.utils.decorators.ContextDecorator - Псевдоним contextlib.ContextDecorator.
  • django.utils._os.abspathu() - Псевдоним os.path.abspath().
  • django.utils._os.upath() и npath() - Эти функции ничего не делают на Python 3.
  • django.utils.six - Удалить использование этой вендорной библиотеки или переключиться на six.
  • django.utils.encoding.python_2_unicode_compatible() - Псевдоним six.python_2_unicode_compatible().
  • django.utils.functional.curry() - Используйте functools.partial() или functools.partialmethod. См. 5b1c389603a353625ae1603ba345147356336afb.
  • django.utils.safestring.SafeBytes - Не используется со времен Django 2.0.

Новое значение по умолчанию для параметра FILE_UPLOAD_PERMISSIONS

В старых версиях параметр FILE_UPLOAD_PERMISSIONS по умолчанию имеет значение None. При значении по умолчанию FILE_UPLOAD_HANDLERS это приводит к тому, что загруженные файлы имеют разные разрешения в зависимости от их размера и используемого обработчика загрузки.

FILE_UPLOAD_PERMISSIONS теперь по умолчанию используется 0o644, чтобы избежать этого несоответствия.

Новые значения по умолчанию для параметров безопасности

Чтобы сделать проекты Django более безопасными по умолчанию, некоторые параметры безопасности теперь имеют более безопасные значения по умолчанию:

Подробнее об этих изменениях см. в разделе Что нового Security section выше.

Разное

  • ContentType.__str__() теперь включает в себя app_label модели, чтобы различать модели с одинаковыми именами в разных приложениях.
  • Поскольку доступ к языку в сессии, а не в cookie, устарел, LocaleMiddleware больше не ищет язык пользователя в сессии, а django.contrib.auth.logout() больше не сохраняет язык сессии после выхода из системы.
  • django.utils.html.escape() теперь использует html.escape() для экранирования HTML. Это преобразует ' в ' вместо прежнего эквивалентного десятичного кода '.
  • Опция django-admin test -k теперь работает как опция unittest -k, а не как сокращение для --keepdb.
  • Удалена поддержка pywatchman < 1.2.0.
  • urlencode() теперь кодирует итерируемые значения так, как они есть при doseq=False, а не итерирует их, что приводит ее в соответствие с функцией стандартной библиотеки urllib.parse.urlencode().
  • Фильтр шаблона intword теперь переводит 1.0 как единственное число, а все остальные числовые значения - как множественное. Это может быть неверно для некоторых языков.
  • Присвоение значения атрибуту ForeignKey или OneToOneField '_id' модели теперь отменяет установку соответствующего поля. После этого обращение к полю приведет к запросу.
  • patch_vary_headers() теперь обрабатывает звездочку '*' в соответствии с RFC 7231#section-7.1.4, т.е. если список имен полей заголовка содержит звездочку, то заголовок Vary будет состоять из одной звездочки '*'.
  • В MySQL 8.0.16+, PositiveIntegerField и PositiveSmallIntegerField теперь включают проверочное ограничение для предотвращения отрицательных значений в базе данных.
  • alias=None добавляется к сигнатуре Expression.get_group_by_cols().
  • RegexPattern, используемый re_path(), больше не возвращает аргументы ключевых слов со значениями None, которые должны быть переданы в представление для необязательных именованных групп, которые отсутствуют.

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

django.utils.encoding.force_text() и smart_text()

Псевдонимы smart_text() и force_text() (начиная с Django 2.0) smart_str() и force_str() устарели. Игнорируйте это устаревание, если ваш код поддерживает Python 2, так как поведение smart_str() и force_str() там отличается.

Разное

  • django.utils.http.urlquote(), urlquote_plus(), urlunquote() и urlunquote_plus() устарели в пользу функций, псевдонимами которых они являются: urllib.parse.quote(), quote_plus(), unquote() и unquote_plus().
  • django.utils.translation.ugettext(), ugettext_lazy(), ugettext_noop(), ungettext() и ungettext_lazy() устарели в пользу функций, псевдонимами которых они являются: django.utils.translation.gettext(), gettext_lazy(), gettext_noop(), ngettext() и ngettext_lazy().
  • Чтобы ограничить создание сессий и, следовательно, благоприятствовать некоторым стратегиям кэширования, django.views.i18n.set_language() перестанет устанавливать язык пользователя в сессии в Django 4.0. Начиная с Django 2.1, язык всегда хранится в cookie LANGUAGE_COOKIE_NAME.
  • django.utils.text.unescape_entities() устарел в пользу html.unescape(). Обратите внимание, что в отличие от unescape_entities(), html.unescape() оценивает ленивые строки немедленно.
  • Чтобы избежать возможной путаницы относительно эффективной области применения, частная внутренняя утилита is_safe_url() переименована в url_has_allowed_host_and_scheme(). То, что URL имеет разрешенный хост и схему, в общем случае не означает, что он «безопасен». Например, он все еще может быть неправильно процитирован. Убедитесь, что вы также используете iri_to_uri() в компоненте пути недоверенных URL.

Функции, удаленные в версии 3.0

Эти функции достигли конца своего цикла устаревания и будут удалены в Django 3.0.

Подробнее об этих изменениях, в том числе о том, как удалить использование этих функций, смотрите Функции, устаревшие в версии 2.0.

  • Модуль django.db.backends.postgresql_psycopg2 удаляется.
  • django.shortcuts.render_to_response() удаляется.
  • Настройка DEFAULT_CONTENT_TYPE удаляется.
  • HttpRequest.xreadlines() удаляется.
  • Убрана поддержка аргумента context в Field.from_db_value() и Expression.convert_value().
  • Аргумент field_name ключевого слова QuerySet.earliest() и latest() удаляется.

Подробнее об этих изменениях, в том числе о том, как удалить использование этих функций, смотрите Функции, устаревшие в версии 2.1.

  • Функция ForceRHR GIS удалена.
  • django.utils.http.cookie_date() удаляется.
  • Библиотеки тегов шаблонов staticfiles и admin_static удалены.
  • django.contrib.staticfiles.templatetags.staticfiles.static() удаляется.
Вернуться на верх