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

1 августа 2018

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

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

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

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

Django 2.1 поддерживает Python 3.5, 3.6 и 3.7. Django 2.0 - последняя версия, поддерживающая Python 3.4. Мы настоятельно рекомендуем и официально поддерживаем только последний выпуск каждой серии.

Что нового в Django 2.1

Разрешение модели «просмотр»

К модели Meta.default_permissions добавляется разрешение «view». Новые разрешения будут созданы автоматически при запуске migrate.

Это позволяет предоставлять пользователям доступ только для чтения к моделям в админке. ModelAdmin.has_view_permission() является новым. Реализация обратно совместима, так как нет необходимости назначать разрешение «просмотр», чтобы позволить пользователям, имеющим разрешение «изменение», редактировать объекты.

Есть несколько backwards incompatible considerations.

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

django.contrib.admin

  • ModelAdmin.search_fields теперь принимает любой поиск, например field__exact.
  • jQuery обновлен с версии 2.2.3 до 3.3.1.
  • Новый метод ModelAdmin.delete_queryset() позволяет настраивать процесс удаления действия «удалить выбранные объекты».
  • Теперь вы можете override the default admin site.
  • Новый атрибут ModelAdmin.sortable_by и метод ModelAdmin.get_sortable_by() позволяют ограничить столбцы, которые могут быть отсортированы на странице списка изменений.
  • Атрибут admin_order_field для элементов в ModelAdmin.list_display теперь может быть выражением запроса.
  • Новый метод ModelAdmin.get_deleted_objects() позволяет настраивать процесс удаления в представлении удаления и действие «удалить выбранное».
  • Шаблоны actions.html, change_list_results.html, date_hierarchy.html, pagination.html, prepopulated_fields_js.html, search_form.html и submit_line.html теперь могут быть overridden per app or per model (помимо глобального переопределения).
  • Инструменты списка изменений администратора и объекта формы изменений теперь могут быть overridden per app, per model, or globally с шаблонами change_list_object_tools.html и change_form_object_tools.html.
  • InlineModelAdmin.has_add_permission() теперь передается родительский объект в качестве второго позиционного аргумента, obj.
  • Действия администратора теперь могут specify permissions ограничить их доступность для определенных пользователей.

django.contrib.auth

django.contrib.gis

  • Новый метод GEOSGeometry.buffer_with_style() представляет собой версию buffer(), которая позволяет настраивать стиль буфера.
  • OpenLayersWidget теперь основан на OpenLayers 4.6.5 (ранее 3.20.1).

django.contrib.sessions

  • Добавлена настройка SESSION_COOKIE_SAMESITE для установки флага SameSite для сессионных cookie-файлов.

Кэш

  • Теперь local-memory cache backend использует стратегию очистки по наименее часто используемому принципу (LRU), а не псевдослучайную.
  • Новый метод touch() low-level cache API обновляет таймаут ключей кэша.

CSRF

  • Добавлена настройка CSRF_COOKIE_SAMESITE для установки флага SameSite для куки-файлов CSRF.

Формы

  • Виджет для ImageField теперь отображается с HTML-атрибутом accept="image/*".

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

  • Добавлена функция get_supported_language_variant().
  • Непереведенные строки для территориальных вариантов языка теперь используют переводы общего языка. Например, непереведенные строки pt_BR используют перевод pt.

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

  • Новая опция inspectdb --include-views позволяет создавать модели для представлений базы данных.
  • Класс BaseCommand теперь использует пользовательский форматтер справки, так что стандартные опции, такие как --verbosity или --settings, появляются последними в выводе справки, предоставляя более заметное место опциям подкласса команды.

Миграции

  • Добавлена поддержка сериализации объектов functools.partialmethod.
  • Для поддержки замороженных сред миграции могут загружаться из файлов .pyc.

Модели

  • Теперь модели могут использовать __init_subclass__() из PEP 487.
  • Теперь BinaryField может быть установлен в editable=True, если вы хотите включить его в формы модели.
  • Добавлен ряд новых функций текстовой базы данных: Chr, Left, LPad, LTrim, Ord, Repeat, Replace, Right, RPad, RTrim и Trim.
  • Новая функция TruncWeek усекает DateField и DateTimeField до понедельника недели.
  • Выражения запросов теперь можно отрицать с помощью знака минус.
  • QuerySet.order_by() и distinct(*fields) теперь поддерживают использование преобразований полей.
  • BooleanField теперь может быть null=True. Это приветствуется вместо NullBooleanField, который, скорее всего, будет устаревшим в будущем.
  • Новый метод QuerySet.explain() отображает план выполнения запроса кверисета в базе данных.
  • QuerySet.raw() теперь поддерживает prefetch_related().

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

  • Добавлено HttpRequest.get_full_path_info().
  • Добавлен аргумент samesite в HttpResponse.set_cookie() для возможности установки флага cookie SameSite.
  • Новый аргумент as_attachment для FileResponse устанавливает заголовок Content-Disposition, чтобы браузер спросил, хочет ли пользователь загрузить файл. FileResponse также пытается установить заголовки Content-Type и Content-Length там, где это необходимо.

Шаблоны

  • Новый фильтр json_script безопасно выводит объект Python как JSON, завернутый в тег <script>, готовый к использованию в JavaScript.

Тесты

  • Добавлена поддержка теста Client для 307 и 308 редиректов.
  • Тест Client теперь сериализует словарь данных запроса как JSON, если content_type='application/json'. Вы можете настроить кодировщик JSON с помощью параметра json_encoder клиента теста.
  • Новый метод SimpleTestCase.assertWarnsMessage() является более простой версией assertWarnsRegex().

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

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

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

  • Для соответствия стандарту PEP 249 исключения, когда база данных не поддерживает функцию, изменены с NotImplementedError на django.db.NotSupportedError.
  • Переименовали флаг признака базы данных allow_sliced_subqueries в allow_sliced_subqueries_with_in.
  • DatabaseOperations.distinct_sql() теперь требует дополнительного аргумента params и возвращает кортеж SQL и параметров вместо строки SQL.
  • DatabaseFeatures.introspected_boolean_field_type превращается из метода в свойство.

django.contrib.gis

  • Удалена поддержка SpatiaLite 4.0.

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

Окончание поддержки MySQL 5.5 со стороны апстрима приходится на декабрь 2018 года. Django 2.1 поддерживает MySQL 5.6 и выше.

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

Окончание поддержки PostgreSQL 9.3 приходится на сентябрь 2018 года. Django 2.1 поддерживает PostgreSQL 9.4 и выше.

Удалена настройка BCryptPasswordHasher по умолчанию PASSWORD_HASHERS

Если вы использовали bcrypt в Django 1.4 или 1.5 (до добавления BCryptSHA256PasswordHasher в Django 1.6), у вас могут быть пароли, использующие хешер BCryptPasswordHasher.

Вы можете проверить, так ли это, следующим образом:

from django.contrib.auth import get_user_model
User = get_user_model()
User.objects.filter(password__startswith='bcrypt$$')

Если вы хотите продолжать разрешать использование этих паролей, вам придется определить параметр PASSWORD_HASHERS (если вы этого еще не сделали) и включить 'django.contrib.auth.hashers.BCryptPasswordHasher'.

Перемещена контекстная переменная шаблона виджета wrap_label

Чтобы исправить отсутствие <label> при использовании RadioSelect и CheckboxSelectMultiple с MultiWidget, контекстная переменная wrap_label теперь отображается как атрибут каждой опции. Например, в пользовательском шаблоне input_option.html измените {% if wrap_label %} на {% if widget.wrap_label %}.

SameSite печенье

Cookies, используемые для django.contrib.sessions, django.contrib.messages и CSRF-защиты Django, теперь по умолчанию устанавливают флаг SameSite на Lax. Браузеры, соблюдающие этот флаг, не будут отправлять эти куки при кросс-оригинальных запросах. Если вы полагаетесь на старое поведение, установите для параметров SESSION_COOKIE_SAMESITE и/или CSRF_COOKIE_SAMESITE значение None.

Соображения по поводу нового разрешения модели «просмотр»

Пользовательские формы администратора должны учитывать случай «только для просмотра

С новым разрешением «view» существующие пользовательские формы администратора могут выдавать ошибки, если у пользователя нет прав на изменение, поскольку форма может обращаться к несуществующим полям. Исправьте это, переопределив ModelAdmin.get_form() и проверяя, есть ли у пользователя права на «изменение», и возвращая форму по умолчанию, если нет:

class MyAdmin(admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        if not self.has_change_permission(request, obj):
            return super().get_form(request, obj, **kwargs)
        return CustomForm

Новое разрешение на представление по умолчанию может предоставить нежелательный доступ к представлениям администратора

Если у вас есть пользовательское разрешение с кодовым именем вида view_<modelname>, новая обработка разрешения просмотра в админке позволит получить доступ к страницам списка изменений и подробностей для этих моделей. Если это нежелательно, необходимо изменить кодовое имя пользовательского разрешения.

Разное

  • Минимальная поддерживаемая версия mysqlclient увеличена с 1.3.3 до 1.3.7.
  • Удалена поддержка SQLite < 3.7.15.
  • Формат даты в директиве Set-Cookie Expires изменен, чтобы следовать стандарту RFC 7231#section-7.1.1.1 вместо стандарта cookie от Netscape. Дефисы, присутствующие в датах типа Tue, 25-Dec-2018 22:26:13 GMT, удалены. Это изменение должно быть просто косметическим, за исключением, возможно, устаревших браузеров, которые не воспринимают новый формат.
  • allowed_hosts теперь является обязательным аргументом частного API django.utils.http.is_safe_url().
  • Атрибут multiple, отображаемый виджетом SelectMultiple, теперь использует синтаксис HTML5 boolean, а не XHTML multiple="multiple".
  • HTML, отображаемый виджетами форм, больше не включает закрывающую косую черту для элементов void, например <br>. Это несовместимо с XHTML, хотя некоторые виджеты уже используют такие аспекты HTML5, как атрибуты boolean.
  • Значение опции empty опции SelectDateWidget изменено с 0 на пустую строку, что в основном может потребовать некоторых корректировок в тестах, сравнивающих HTML.
  • User.has_usable_password() и функция is_password_usable() больше не возвращают False, если пароль равен None или пустой строке, или если в пароле используется хешер, не входящий в настройки PASSWORD_HASHERS. Это недокументированное поведение было регрессией в Django 1.6 и не позволяло пользователям с такими паролями запрашивать сброс пароля. Проверьте свой код, чтобы убедиться, что ваше использование этих API не опирается на старое поведение.
  • Поскольку миграции теперь загружаются из файлов .pyc, вам может понадобиться удалить их, если вы работаете в смешанной среде Python 2 и Python 3.
  • Использование None в качестве значения поиска django.contrib.postgres.fields.JSONField теперь соответствует объектам, имеющим указанный ключ и нулевое значение, а не объектам, не имеющим ключа.
  • CSS-класс администратора field-box переименован в fieldBox, чтобы избежать конфликтов с классом, присвоенным полям модели с именем «box».
  • Поскольку шаблоны администратора actions.html, change_list_results.html, date_hierarchy.html, pagination.html, prepopulated_fields_js.html, search_form.html и submit_line.html теперь могут быть переопределены для каждого приложения или каждой модели, вам может понадобиться переименовать существующие шаблоны с этими именами, которые были написаны для другой цели.
  • QuerySet.raw() теперь кэширует свои результаты, как обычные наборы запросов. Используйте iterator(), если вам не нужно кэширование.
  • Метод маршрутизатора базы данных allow_relation() вызывается в большем количестве случаев. Неправильно написанные маршрутизаторы могут нуждаться в соответствующем обновлении.
  • Переводы больше не деактивируются перед запуском команд управления. Если ваша пользовательская команда требует деактивации переводов (например, для вставки непереведенного содержимого в базу данных), используйте новый параметр @no_translations decorator.
  • Команды управления больше не позволяют использовать сокращенные формы аргументов --settings и --pythonpath.
  • Частная константа django.db.models.sql.constants.QUERY_TERMS удаляется. Методы get_lookup() и get_lookups() константы Lookup Registration API могут быть подходящей альтернативой. По сравнению с константой QUERY_TERMS, они позволяют вашему коду также учитывать любые зарегистрированные пользовательские поиски.
  • Совместимость с py-bcrypt удалена, поскольку она не поддерживается. Вместо него используйте bcrypt.

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

Разное

  • Функция ForceRHR GIS устарела в пользу новой функции ForcePolygonCW.
  • django.utils.http.cookie_date() устарел в пользу http_date(), который следует формату последнего RFC.
  • {% load staticfiles %} и {% load admin_static %} устарели в пользу {% load static %}, который работает так же.
  • django.contrib.staticfiles.templatetags.static() устарел в пользу django.templatetags.static.static().
  • Поддержка методов InlineModelAdmin.has_add_permission(), которые не принимают obj в качестве второго позиционного аргумента, будет удалена в Django 3.0.

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

Эти функции достигли конца цикла устаревания и будут удалены в Django 2.1. Смотрите Функции, устаревшие в версии 1.1 для подробностей, включая то, как удалить использование этих функций.

  • contrib.auth.views.login(), logout(), password_change(), password_change_done(), password_reset(), password_reset_done(), password_reset_confirm() и password_reset_complete() удаляются.
  • Параметр extra_context из contrib.auth.views.logout_then_login() удаляется.
  • django.test.runner.setup_databases() удаляется.
  • django.utils.translation.string_concat() удаляется.
  • django.core.cache.backends.memcached.PyLibMCCache больше не поддерживает передачу параметров поведения pylibmc в качестве атрибутов верхнего уровня OPTIONS.
  • Параметр host из django.utils.http.is_safe_url() удаляется.
  • Убрано глушение исключений, возникающих при отрисовке тега шаблона {% include %}.
  • DatabaseIntrospection.get_indexes() удаляется.
  • Метод authenticate() бэкендов аутентификации требует request в качестве первого позиционного аргумента.
  • Декоратор django.db.models.permalink() удаляется.
  • Настройка USE_ETAGS удалена. CommonMiddleware и django.utils.cache.patch_response_headers() больше не устанавливают ETags.
  • Атрибут Model._meta.has_auto_field удаляется.
  • Поддержка url() в группах регулярных выражений ((?i), (?L), (?m), (?s) и (?u)) для встроенных флагов удалена.
  • Устранена поддержка методов Widget.render() без аргумента renderer.
Вернуться на верх