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

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

1 августа 2016 г.

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

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

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

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

Как и Django 1.9, Django 1.10 требует Python 2.7, 3.4 или 3.5. Мы настоятельно рекомендуем и официально поддерживаем только последнюю версию каждой серии.

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

Полнотекстовый поиск PostgreSQL

django.contrib.postgres теперь включает коллекцию функций базы данных, позволяющую использовать систему полнотекстового поиска. Вы можете выполнять поиск по нескольким полям в своей реляционной базе данных, комбинировать поиск с другими поисками, использовать различные языковые конфигурации и весовые коэффициенты, а также ранжировать результаты по релевантности.

Теперь он также включает поддержку триграмм с использованием поиска trigram_similar и выражений TrigramSimilarity и TrigramDistance.

Промежуточное программное обеспечение нового стиля

Введен новый стиль промежуточного программного обеспечения, чтобы решить проблему отсутствия строгого разделения запросов и ответов в старом стиле промежуточного программного обеспечения, описанного в DEP 0005. Вам нужно будет адаптировать старое пользовательское промежуточное программное обеспечение и переключиться с настройки MIDDLEWARE_CLASSES на новую настройку MIDDLEWARE, чтобы воспользоваться преимуществами улучшений.

Официальная поддержка имен пользователей Unicode

Модель User в django.contrib.auth изначально принимала в именах пользователей только буквы и цифры ASCII. Хотя это не был преднамеренный выбор, символы Юникода всегда принимались при использовании Python 3.

Валидатор имени пользователя теперь явно принимает символы Юникода по умолчанию только в Python 3.

Пользовательские модели пользователей могут использовать новый ASCIIUsernameValidator или UnicodeUsernameValidator.

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

django.contrib.admin

  • Для сайтов, работающих по подпути, URL-адрес по умолчанию для ссылки «Просмотр сайта» <django.contrib.admin.AdminSite.site_url>` в верхней части каждой страницы администрирования теперь будет указывать на request.META['SCRIPT_NAME'], если он установлен, вместо /.

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

  • Весь встроенный JavaScript удален, поэтому вы можете включить HTTP-заголовок Content-Security-Policy, если хотите.

  • Новый атрибут InlineModelAdmin.classes позволяет указывать классы во встроенных наборах полей. Строки с классом «collapse» изначально будут свернуты, а в их заголовке будет небольшая ссылка «показать».

  • Если у пользователя нет разрешения на добавление, блок object-tools в списке изменений модели теперь будет отображаться (без кнопки добавления). В данном случае это упрощает добавление пользовательских инструментов.

  • Модель LogEntry теперь хранит сообщения об изменениях в структуре JSON, чтобы сообщение можно было динамически перевести с использованием текущего активного языка. Новый метод LogEntry.get_change_message() теперь является предпочтительным способом получения сообщения об изменении.

  • Выбранные объекты для полей в ModelAdmin.raw_id_fields теперь имеют ссылку на форму изменения объекта.

  • Добавлены варианты «Нет даты» и «Есть дата» для DateFieldListFilter, если поле имеет значение NULL.

  • Библиотека jQuery, встроенная в админку, обновлена ​​с версии 2.1.4 до 2.2.3.

django.contrib.auth

  • Добавлена ​​поддержка хэша пароля Argon2. Его рекомендуется использовать вместо PBKDF2, однако он не используется по умолчанию, поскольку требует сторонней библиотеки.

  • Число итераций по умолчанию для хэшера паролей PBKDF2 увеличено на 25%. Это обратно совместимое изменение не повлияет на пользователей, которые создали подкласс django.contrib.auth.hashers.PBKDF2PasswordHasher, чтобы изменить значение по умолчанию.

  • Представление django.contrib.auth.views.logout() отправляет заголовки «без кэша», чтобы предотвратить проблему, когда Safari кэширует перенаправления и не позволяет пользователю выйти из системы.

  • В django.contrib.auth.login() добавлен необязательный аргумент backend, позволяющий использовать его без учетных данных.

  • Новая настройка LOGOUT_REDIRECT_URL управляет перенаправлением представления django.contrib.auth.views.logout(), если представление не получает аргумент next_page.

  • Новый параметр redirect_authenticated_user для представления django.contrib.auth.views.login() позволяет перенаправлять аутентифицированных пользователей, посещающих страницу входа.

  • Новые AllowAllUsersModelBackend и AllowAllUsersRemoteUserBackend игнорируют значение User.is_active, а ModelBackend и RemoteUserBackend теперь отклоняют неактивных пользователей.

django.contrib.gis

  • Поиск расстояния теперь принимает выражения в качестве параметра значения расстояния.

  • Новое свойство GEOSGeometry.unary_union вычисляет объединение всех элементов этой геометрии.

  • Добавлен двоичный предикат GEOSGeometry.covers().

  • Добавлен метод GDALBand.statistics() и атрибуты mean и std.

  • Добавлена ​​поддержка агрегата MakeLine и функции GeoHash в SpatiaLite.

  • Добавлена ​​поддержка функций Difference, Intersection и SymDifference в MySQL.

  • Добавлена ​​поддержка создания экземпляров пустой геометрии GEOS.

  • Новые свойства trim и precision WKTWriter позволяют контролировать вывод дробной части координат в WKT.

  • Добавлены свойства LineString.closed и MultiLineString.closed.

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

  • Добавлена ​​возможность реплицировать входные данные в методе GDALBand.data(). Данные полосы теперь можно эффективно обновлять повторяющимися значениями.

  • Добавлены функции базы данных IsValid и MakeValid, а также поиск isvalid, все для PostGIS. Это позволяет фильтровать и исправлять неверную геометрию на стороне базы данных.

  • Добавлена ​​поддержка растров для всех пространственных поисков.

django.contrib.postgres

  • Для удобства HStoreField теперь преобразует свои ключи и значения в строки.

django.contrib.sessions

  • Команда управления clearsessions теперь удаляет файловые сеансы.

django.contrib.sites

django.contrib.staticfiles

  • Тег шаблона static теперь использует django.contrib.staticfiles, если он находится в INSTALLED_APPS. Это особенно полезно для сторонних приложений, которые теперь всегда могут использовать {% load static %} (вместо {% load staticfiles %} или {% load static from staticfiles %}) и не беспокоиться о том, установлено ли приложение staticfiles или нет.

  • Вы можете более легко настроить опцию collectstatic --ignore с помощью специального AppConfig.

Кэш

  • Серверная часть файлового кэша теперь использует самый высокий протокол травления.

CSRF

  • Настройка по умолчанию: CSRF_FAILURE_VIEW, views.csrf.csrf_failure(), теперь принимает необязательный параметр template_name, по умолчанию равный 403_csrf.html, для управления шаблоном, используемым для визуализации страницы.

  • Для защиты от атак BREACH механизм защиты CSRF теперь меняет значение токена формы при каждом запросе (при этом сохраняя инвариантный секрет, который можно использовать для проверки различных токенов).

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

  • Вычитание временных данных было унифицировано на всех серверах.

  • Если база данных поддерживает это, серверные части могут установить DatabaseFeatures.can_return_ids_from_bulk_insert=True и реализовать DatabaseOperations.fetch_returned_insert_ids() для установки первичных ключей для объектов, созданных с помощью QuerySet.bulk_create().

  • В методы as_sql() для различных выражений добавлены аргументы ключевых слов (Func, When, Case и OrderBy), позволяющие бэкэндам базы данных настраивать их без изменения self, что небезопасно при использовании разных бэкендов базы данных. Пример см. в параметрах arg_joiner и **extra_context Func.as_sql().

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

  • Серверные части хранилища теперь представляют API с учетом часового пояса с новыми методами get_accessed_time(), get_created_time() и get_modified_time(). Они возвращают datetime с учетом часового пояса, если USE_TZ имеет значение True, и наивное datetime в локальном часовом поясе в противном случае.

  • Новый метод Storage.generate_filename() упрощает реализацию пользовательских хранилищ, которые не используют вызовы os.path ранее в FileField.

Формы

  • Форма и виджет «Медиа» теперь обслуживаются с использованием django.contrib.staticfiles, если он установлен.

  • Тег <input>, отображаемый с помощью CharField, теперь включает атрибут minlength, если поле имеет min_length.

  • Обязательные поля формы теперь имеют HTML-атрибут required. Установите для нового атрибута Form.use_required_attribute значение False, чтобы отключить его. Атрибут required не включается в формы наборов форм, поскольку проверка браузера может быть неправильной при добавлении и удалении наборов форм.

Общие представления

  • Класс View теперь можно импортировать из django.views.

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

  • Вспомогательную функцию i18n_patterns() теперь можно использовать в корневом URLConf, указанном с помощью request.urlconf.

  • Установив для нового параметра prefix_default_language для i18n_patterns() значение False, вы можете разрешить доступ к языку по умолчанию без префикса URL.

  • set_language() теперь возвращает код состояния 204 (нет содержимого) для запросов AJAX, когда в POST или GET нет параметра next.

  • Представления на основе классов JavaScriptCatalog и JSONCatalog заменяют устаревшие представления на основе функций javascript_catalog() и json_catalog(). Новые представления почти эквивалентны старым, за исключением того, что по умолчанию новые представления собирают все строки JavaScript в домене перевода djangojs из всех установленных приложений, а не только строки JavaScript из LOCALE_PATHS.

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

  • call_command() теперь возвращает значение, возвращенное методом command.handle().

  • Новая опция check --fail-level позволяет указать уровень сообщения, при котором команда завершится с ненулевым статусом.

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

  • makemigrations теперь отображает путь к файлам миграции, которые он генерирует.

  • Опция shell --interface теперь принимает python, чтобы принудительно использовать «простой» интерпретатор Python.

  • Новая опция shell --command позволяет вам запустить команду от имени Django и выйти вместо открытия интерактивной оболочки.

  • Добавлено предупреждение в dumpdata, если указана модель прокси (что приводит к отсутствию вывода) без ее конкретного родителя.

  • Новый атрибут BaseCommand.requires_migrations_checks может быть установлен в True, если вы хотите, чтобы ваша команда выводила предупреждение, как это делает runserver, если набор миграций на диске не соответствует миграциям в базе данных.

  • Чтобы облегчить тестирование, call_command() теперь принимает объект команды в качестве первого аргумента.

  • Команда shell поддерживает завершение табуляции в системах, использующих libedit, например. macOS.

  • Команда inspectdb позволяет вам выбрать, какие таблицы следует проверять, указав их имена в качестве аргументов.

Миграции

  • Добавлена ​​поддержка сериализации объектов enum.Enum.

  • Добавлен аргумент elidable в операции RunSQL и RunPython, чтобы их можно было удалить при сжатии миграций.

  • Добавлена ​​поддержка неатомарных миграций путем установки атрибута atomic для Migration.

  • Команды migrate и makemigrations теперь проверяют целостность истории миграции. Если они обнаруживают какие-то непримененные зависимости примененной миграции, возникает InconsistentMigrationHistory.

  • Сигналы pre_migrate() и post_migrate() теперь отправляют свои plan и apps миграции.

Модели

  • Обратные внешние ключи из прокси-моделей теперь распространяются на их конкретный класс. Обратное отношение, прикрепленное ForeignKey, указывающее на прокси-модель, теперь доступно как дескриптор в прокси-классе модели, и на него можно ссылаться при фильтрации набора запросов.

  • Новый метод Field.rel_db_type() возвращает тип данных столбца базы данных для таких полей, как ForeignKey и OneToOneField, которые указывают на другое поле.

  • Атрибут класса arity добавляется в Func. Этот атрибут можно использовать для установки количества аргументов, которые принимает функция.

  • Добавлен BigAutoField, который действует очень похоже на AutoField, за исключением того, что он гарантированно помещает числа от 1 до 9223372036854775807.

  • QuerySet.in_bulk() может быть вызван без каких-либо аргументов для возврата всех объектов в наборе запросов.

  • related_query_name теперь поддерживает интерполяцию меток приложения и классов с использованием строк '%(app_label)s' и '%(class)s'.

  • Разрешено переопределение полей модели, унаследованных от абстрактных базовых классов.

  • Функция prefetch_related_objects() теперь является общедоступным API.

  • QuerySet.bulk_create() устанавливает первичный ключ для объектов при использовании PostgreSQL.

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

  • Прокси-модель теперь может наследовать несколько прокси-моделей, которые имеют общий неабстрактный родительский класс.

  • Добавлены функции Extract для извлечения компонентов даты и времени в виде целых чисел, таких как год и час.

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

  • Model.__init__() теперь устанавливает значения виртуальных полей из аргументов ключевого слова.

  • Новые параметры Meta.base_manager_name и Meta.default_manager_name позволяют управлять _base_manager и _default_manager соответственно.

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

  • Добавлен request.user в представление отладки.

  • Добавлены методы HttpResponse readable() и seekable(), чтобы сделать экземпляр потокоподобным объектом и позволить обернуть его с помощью io.TextIOWrapper.

  • Добавлены атрибуты HttpRequest.content_type и content_params, которые анализируются из заголовка CONTENT_TYPE.

  • Анализатор request.COOKIES упрощен, чтобы лучше соответствовать поведению браузеров. request.COOKIES теперь может содержать файлы cookie, которые недействительны в соответствии с RFC 6265, но их можно установить через document.cookie.

Сериализация

  • django.core.serializers.json.DjangoJSONEncoder теперь знает, как сериализовать ленивые строки, обычно используемые для переводимого контента.

Шаблоны

  • Добавлена ​​опция autoescape в DjangoTemplates и в класс Engine.

  • В тег if добавлены операторы сравнения is и is not.

  • Разрешено dictsort упорядочивать список списков по элементу по указанному индексу.

  • Контекстный процессор debug() содержит запросы для всех псевдонимов базы данных, а не только для псевдонима по умолчанию.

  • Добавлена ​​поддержка относительного пути для строковых аргументов тегов шаблона extends и include.

Тесты

  • Чтобы лучше выявлять ошибки, TestCase теперь проверяет отложенные ограничения базы данных в конце каждого теста.

  • Тесты и тестовые примеры можно помечать тегами и запускать выборочно с помощью новых опций test --tag и test --exclude-tag.

  • Теперь вы можете входить в систему и использовать сеансы с тестовым клиентом, даже если django.contrib.sessions не находится в INSTALLED_APPS.

URL-адреса

  • Дополнение в django.setup() позволяет разрешению URL-адресов, которое происходит вне цикла запрос/ответ (например, в командах управления и автономных скриптах), учитывать FORCE_SCRIPT_NAME, когда он установлен.

Валидаторы

  • URLValidator теперь ограничивает длину меток доменных имен до 63 символов, а общую длину доменных имен до 253 символов на RFC 1034.

  • int_list_validator() теперь принимает необязательный логический параметр allow_negative, по умолчанию равный False, чтобы разрешить отрицательные целые числа.

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

Предупреждение

В дополнение к изменениям, изложенным в этом разделе, обязательно просмотрите Функции удалены в версии 1.10 для функций, срок устаревания которых достиг конца и поэтому был удален. Если вы не обновили свой код в течение срока прекращения поддержки определенной функции, ее удаление может выглядеть как обратно несовместимое изменение.

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

  • «AreaField» ГИС использует неопределенный базовый числовой тип, который на практике может быть любым числовым типом Python. Значения decimal.Decimal, полученные из базы данных, теперь преобразуются в float, чтобы их было проще комбинировать со значениями, используемыми библиотеками ГИС.

  • Чтобы включить временное вычитание, вы должны установить флаг функции базы данных support_temporal_subtraction в значение True и реализовать метод DatabaseOperations.subtract_temporals(). Этот метод должен возвращать SQL и параметры, необходимые для вычисления разницы в микросекундах между аргументами lhs и rhs в типе данных, используемом для хранения DurationField.

_meta.get_fields() возвращает согласованные обратные поля для прокси-моделей.

До Django 1.10 метод get_fields() возвращал разные обратные поля при вызове прокси-модели по сравнению с ее прокси-конкретным классом. Это несоответствие было исправлено путем возврата полного набора полей, указывающих на конкретный класс или один из его прокси в обоих случаях.

AbstractUser.username max_length увеличено до 150

Включена миграция для django.contrib.auth.models.User.username. Если у вас есть пользовательская модель, унаследованная от «AbstractUser», вам необходимо сгенерировать и применить миграцию базы данных для вашей пользовательской модели.

Мы рассматривали возможность увеличения длины до 254 символов, чтобы упростить использование адресов электронной почты (длина которых ограничена 254 символами) в качестве имен пользователей, но отклонили эту идею из-за ограничений MySQL. При использовании кодировки utf8mb4 (рекомендуется для правильной поддержки Unicode) MySQL по умолчанию может создавать только уникальные индексы длиной 191 символ. Поэтому, если вам нужна более длинная длина, используйте собственную модель пользователя.

Если вы хотите сохранить ограничение в 30 символов для имен пользователей, используйте специальную форму при создании пользователя или изменении имен пользователей:

from django.contrib.auth.forms import UserCreationForm


class MyUserCreationForm(UserCreationForm):
    username = forms.CharField(
        max_length=30,
        help_text="Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.",
    )

Если вы хотите сохранить это ограничение в администраторе, установите UserAdmin.add_form для использования этой формы:

from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.models import User


class UserAdmin(BaseUserAdmin):
    add_form = MyUserCreationForm


admin.site.unregister(User)
admin.site.register(User, UserAdmin)

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

Поддержка исходной версии PostgreSQL 9.1 заканчивается в сентябре 2016 года. Как следствие, Django 1.10 устанавливает PostgreSQL 9.2 как минимальную официально поддерживаемую версию.

Вывод runserver проходит протоколирование

Обработка запросов и ответов на команду runserver отправляется в регистратор django-server-logger вместо sys.stderr. Если вы отключите конфигурацию ведения журнала Django или замените ее своей собственной, вам нужно будет добавить соответствующую конфигурацию ведения журнала, если вы хотите видеть этот вывод:

LOGGING = {
    # ...
    "formatters": {
        "django.server": {
            "()": "django.utils.log.ServerFormatter",
            "format": "[%(server_time)s] %(message)s",
        }
    },
    "handlers": {
        "django.server": {
            "level": "INFO",
            "class": "logging.StreamHandler",
            "formatter": "django.server",
        },
    },
    "loggers": {
        "django.server": {
            "handlers": ["django.server"],
            "level": "INFO",
            "propagate": False,
        }
    },
}

Тестовые модели auth.CustomUser и auth.ExtensionUser были удалены.

С момента появления миграций для дополнительных приложений в Django 1.8 таблицы этих пользовательских тестовых моделей больше не создавались, что делало их непригодными для использования в контексте тестирования.

Реестр приложений больше не заполняется автоматически при распаковке моделей за пределами Django.

Реестр приложений больше не заполняется автоматически при разборе моделей. Это было добавлено в Django 1.7.2 как попытка разрешить распаковку моделей за пределами Django, например, в RQ-воркере, без вызова django.setup(), но это создает возможность взаимоблокировки. Чтобы адаптировать свой код для RQ, вы можете предоставить свой собственный рабочий скрипт <https://python-rq.org/docs/workers/>`_, который вызывает ``django.setup().

Удалена проверка присвоения значения NULL для полей внешнего ключа, отличных от NULL.

В более старых версиях присвоение None необнуляемому элементу ForeignKey или OneToOneField вызывало ошибку ValueError(„Невозможно назначить None: «model.field» не допускает нулевых значений.“)``. Для согласованности с другими полями модели, у которых нет аналогичной проверки, эта проверка удалена.

Удалены слабые хешеры паролей из настройки PASSWORD_HASHERS по умолчанию.

Django 0.90 хранил пароли в виде несоленого MD5. В Django 0.91 добавлена ​​поддержка соленого SHA1 с автоматическим обновлением паролей при входе пользователя в систему. В Django 1.4 добавлен PBKDF2 в качестве хэшера паролей по умолчанию.

Если у вас есть старый проект Django с паролями, закодированными в формате MD5 или SHA1 (даже солеными), имейте в виду, что их можно довольно легко взломать с помощью современного оборудования. Чтобы пользователи Django признавали дальнейшее использование слабых хешеров, из настройки по умолчанию PASSWORD_HASHERS удалены следующие хешеры:

  • "django.contrib.auth.hashers.SHA1PasswordHasher"

  • "django.contrib.auth.hashers.MD5PasswordHasher"

  • "django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher"

  • "django.contrib.auth.hashers.UnsaltedMD5PasswordHasher"

  • "django.contrib.auth.hashers.CryptPasswordHasher"

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

Вы можете проверить, есть ли в вашей базе данных какие-либо удаленные хэши, например:

from django.contrib.auth import get_user_model

User = get_user_model()

# Unsalted MD5/SHA1:
User.objects.filter(password__startswith="md5$$")
User.objects.filter(password__startswith="sha1$$")
# Salted MD5/SHA1:
User.objects.filter(password__startswith="md5$").exclude(password__startswith="md5$$")
User.objects.filter(password__startswith="sha1$").exclude(password__startswith="sha1$$")
# Crypt hasher:
User.objects.filter(password__startswith="crypt$$")

from django.db.models import CharField
from django.db.models.functions import Length

CharField.register_lookup(Length)
# Unsalted MD5 passwords might not have an 'md5$$' prefix:
User.objects.filter(password__length=32)

Методы Field.get_prep_lookup() и Field.get_db_prep_lookup() удалены.

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

from django.db.models import Field
from django.db.models.lookups import Exact


class MyField(Field): ...


class MyFieldExact(Exact):
    def get_prep_lookup(self):
        # do_custom_stuff_for_myfield
        ...


MyField.register_lookup(MyFieldExact)

django.contrib.gis

  • Поддержка SpatiaLite < 3.0 и GEOS < 3.3 прекращена.

  • Псевдоним обратной совместимости add_postgis_srs() для django.contrib.gis.utils.add_srs_entry() удален.

  • В Oracle/GIS агрегатная функция Area теперь возвращает значение float вместо decimal.Decimal. (Он все еще завернут в квадратные метры.)

  • Представление GEOSGeometry по умолчанию (выходные данные WKT) обрезается по умолчанию. То есть вместо POINT (23.0000000000000000 5.5000000000000000) вы получите POINT (23 5.5).

Максимальный размер тела запроса и количество параметров GET/POST ограничены.

Две новые настройки помогают смягчить атаки типа «отказ в обслуживании» посредством больших запросов:

  • DATA_UPLOAD_MAX_MEMORY_SIZE ограничивает размер тела запроса. Загрузка файлов не учитывается в этом лимите.

  • DATA_UPLOAD_MAX_NUMBER_FIELDS ограничивает количество анализируемых параметров GET/POST.

Приложениям, которые получают сообщения необычно большой формы, возможно, потребуется настроить эти параметры.

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

  • repr() из QuerySet заключен в <QuerySet >, чтобы исключить неоднозначность его из простого списка при отладке.

  • utils.version.get_version() возвращает версии-кандидаты на выпуск, соответствующие PEP 440 (например, „1.10rc1“ вместо „1.10c1“).

  • Значения токена CSRF теперь должны быть строками из 64 букв и цифр; значения из 32 букв и цифр, установленные по умолчанию в старых версиях Django, автоматически заменяются строками из 64 символов. Остальные значения считаются недействительными. Это должно коснуться только разработчиков или пользователей, которые заменяют эти токены.

  • Параметр LOGOUT_URL удален, поскольку Django не использовал его с версии до версии 1.0. Если вы используете его в своем проекте, вы можете добавить его в настройки вашего проекта. Значением по умолчанию было '/accounts/logout/'.

  • Объекты с методом close(), такие как файлы и генераторы, переданные в HttpResponse, теперь закрываются немедленно, а не тогда, когда сервер WSGI вызывает close() в ответе.

  • Избыточный вызов transaction.atomic() в QuerySet.update_or_create() удален. Это может повлиять на количество запросов, проверенных с помощью TransactionTestCase.assertNumQueries().

  • Поддержка Skip_validation в BaseCommand.execute(**options) удалена. Вместо этого используйте Skip_checks (добавлен в Django 1.7).

  • loaddata теперь вызывает CommandError вместо отображения предупреждения, когда указанный файл фикстуры не найден.

  • Вместо прямого доступа к атрибуту LogEntry.change_message теперь лучше вызвать метод LogEntry.get_change_message(), который предоставит сообщение на текущем языке.

  • Представления ошибок по умолчанию теперь вызывают «TemplateDoesNotExist», если указано несуществующее «template_name».

  • Неиспользуемый аргумент ключевого слова «choices» метода «render()» виджетов «Select» и «SelectMultiple» удален. Аргумент choices метода render_options() также удаляется, делая selected_choices первым аргументом.

  • Тесты, нарушающие отложенные ограничения базы данных, теперь будут вызывать ошибку при запуске в базе данных, поддерживающей отложенные ограничения.

  • Встроенные команды управления теперь используют индексацию ключей в options, например. options['verbosity'] вместо options.get() и больше не выполняет никакого приведения типов. Это может быть проблемой, если вы вызываете команды, используя Command.execute() (который обходит анализатор аргументов, который устанавливает значение по умолчанию) вместо call_command(). Вместо вызова Command.execute() передайте объект команды в качестве первого аргумента в call_command().

  • ModelBackend и RemoteUserBackend теперь отклоняют неактивных пользователей. Это означает, что неактивные пользователи не могут войти в систему и будут отключены, если они переключятся с is_active=True на False. Если вам нужно предыдущее поведение, используйте вместо этого новый AllowAllUsersModelBackend или AllowAllUsersRemoteUserBackend в AUTHENTICATION_BACKENDS.

  • В свете предыдущего изменения метод login() тестового клиента больше не всегда отклоняет неактивных пользователей, а вместо этого делегирует это решение серверной части аутентификации. force_login() также делегирует принятие решения серверу аутентификации, поэтому, если вы используете серверы по умолчанию, вам необходимо использовать активного пользователя.

  • django.views.i18n.set_language() теперь может возвращать код состояния 204 для запросов AJAX.

  • Атрибут base_field RangeField теперь является типом поля, а не экземпляром поля. Если вы создали собственный подкласс RangeField, вам следует изменить атрибут base_field.

  • Классы промежуточного программного обеспечения теперь инициализируются при запуске сервера, а не во время первого запроса.

  • Если вы переопределяете is_authenticated() или is_anonymous() в пользовательской модели пользователя, вы должны преобразовать их в атрибуты или свойства, как описано в примечании об устаревании.

  • При использовании ModelAdmin.save_as=True кнопка «Сохранить как новый» теперь перенаправляет к представлению изменений для нового объекта, а не к списку изменений модели. Если вам нужно предыдущее поведение, установите для нового атрибута ModelAdmin.save_as_continue значение False.

  • Обязательные поля формы теперь имеют HTML-атрибут required. Установите для атрибута Form.use_required_attribute значение False, чтобы отключить его. Вы также можете добавить атрибут novalidate в <form>, если вам не нужна проверка браузера. Чтобы отключить атрибут required в пользовательских виджетах, переопределите метод Widget.use_required_attribute().

  • Обработчик WSGI больше не удаляет содержимое ответов из запросов HEAD или ответов с кодом статуса 100–199, 204 или 304. Большинство веб-серверов уже реализуют такое поведение. К ответам, полученным с помощью тестового клиента Django, по-прежнему применяются эти «исправления ответов».

  • Model.__init__() теперь получает django.db.models.DEFERRED в качестве значения отложенных полей.

  • Атрибут Model._deferred удаляется как классы динамической модели при использовании QuerySet.defer() и only().

  • Storage.save() больше не заменяет '\' на '/'. Это поведение перенесено в FileSystemStorage, поскольку это деталь реализации, специфичная для хранилища. Любой пользователь Windows с собственной реализацией хранилища, использующей это поведение, должен будет реализовать его в методе save() пользовательского хранилища.

  • Частные FileField методы get_directory_name() и get_filename() больше не вызываются (и теперь считаются устаревшими), что является изменением обратной несовместимости для пользователей, переопределяющих эти методы в настраиваемых полях. Чтобы адаптировать такой код, вместо этого переопределите FileField.generate_filename() или Storage.generate_filename(). Возможно, также можно использовать upload_to.

  • Тема письма, отправляемого AdminEmailHandler, больше не обрезается до 989 символов. Если вы рассчитывали на ограниченную длину, сократите тему самостоятельно.

  • Частные выражения django.db.models.expressions.Date и DateTime удалены. Новые выражения Trunc предоставляют ту же функциональность.

  • Атрибуты _base_manager и _default_manager удалены из экземпляров модели. Они остаются доступными в классе модели.

  • Доступ к удаленному полю в экземпляре модели, например. после del obj.field перезагружает значение поля вместо вызова AttributeError.

  • Если вы создадите подкласс AbstractBaseUser и переопределите clean(), убедитесь, что он вызывает super(). AbstractBaseUser.normalize_username() вызывается в новом методе AbstractBaseUser.clean().

  • Частный API django.forms.models.model_to_dict() возвращает набор запросов, а не список первичных ключей для ManyToManyFields.

  • Если установлен django.contrib.staticfiles, тег шаблона static использует хранилище staticfiles для создания URL-адреса, а не просто объединяет значение с STATIC_ROOT. Новый подход кодирует URL-адрес, который может быть обратно несовместим в таких случаях, как включение фрагмента в путь, например {% static 'img.svg#fragment' %}, поскольку # закодирован как %23. Чтобы адаптироваться, переместите фрагмент за пределы тега шаблона: {% static 'img.svg' %}#fragment.

  • Когда USE_L10N имеет значение True, локализация теперь применяется для фильтров date и time, когда не указана строка формата. Спецификаторы DATE_FORMAT и TIME_FORMAT из активной локали используются вместо одноименных настроек.

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

Прямое присвоение обратному внешнему ключу или отношению «многие ко многим».

Вместо назначения связанных объектов с помощью прямого присвоения:

>>> new_list = [obj1, obj2, obj3]
>>> e.related_set = new_list

Используйте метод set(), добавленный в Django 1.9:

>>> e.related_set.set([obj1, obj2, obj3])

Это предотвращает путаницу в назначении, приводящую к неявному сохранению.

Storage API без учета часового пояса

Старые, не учитывающие часовой пояс методы accessed_time(), create_time() и modified_time() устарели в пользу новых методов get_*_time().

Сторонние серверные системы хранения должны реализовать новые методы и пометить старые как устаревшие. До тех пор новые методы get_*_time() в базовом классе Storage преобразуют datetimes из старых методов по мере необходимости и при этом выдают предупреждение об устаревании.

Сторонние серверные системы хранения могут сохранять старые методы, если они хотят поддерживать более ранние версии Django.

django.contrib.gis

  • Методы get_srid() и set_srid() GEOSGeometry устарели в пользу свойства srid.

  • Методы get_x(), set_x(), get_y(), set_y(), get_z() и set_z() Point устарели в пользу свойств x, y и z.

  • Методы get_coords() и set_coords() Point устарели в пользу свойства tuple.

  • Свойство cascaded_union MultiPolygon устарело в пользу свойства unary_union.

  • Функция django.contrib.gis.utils.precision_wkt() устарела в пользу WKTWriter.

Поле модели CommaSeparatedIntegerField

CommaSeparatedIntegerField устарел в пользу CharField с валидатором validate_comma_separated_integer_list():

from django.core.validators import validate_comma_separated_integer_list
from django.db import models


class MyModel(models.Model):
    numbers = models.CharField(..., validators=[validate_comma_separated_integer_list])

Если вы используете Oracle, CharField использует другой тип поля базы данных (NVARCHAR2), чем CommaSeparatedIntegerField (VARCHAR2). В зависимости от настроек вашей базы данных это может означать разную кодировку и, следовательно, разную длину (в байтах) для одного и того же содержимого. Если ваши сохраненные значения длиннее, чем предел NVARCHAR2 в 4000 байт, вместо этого вам следует использовать TextField (NCLOB). В этом случае, если у вас есть какие-либо запросы, которые группируются по полю (например, аннотирование модели с помощью агрегирования или использование distinct()), вам нужно будет изменить их (чтобы отложить поле).

__search поиск по запросу

Поиск search, который поддерживает только MySQL и имеет крайне ограниченные возможности, устарел. Замените его пользовательским поиском:

from django.db import models


class Search(models.Lookup):
    lookup_name = "search"

    def as_mysql(self, compiler, connection):
        lhs, lhs_params = self.process_lhs(compiler, connection)
        rhs, rhs_params = self.process_rhs(compiler, connection)
        params = lhs_params + rhs_params
        return "MATCH (%s) AGAINST (%s IN BOOLEAN MODE)" % (lhs, rhs), params


models.CharField.register_lookup(Search)
models.TextField.register_lookup(Search)

Использование User.is_authenticated() и User.is_anonymous() в качестве методов.

Методы is_authenticated() и is_anonymous() классов AbstractBaseUser и AnonymousUser теперь являются свойствами. Они по-прежнему будут работать как методы до Django 2.0, но теперь для всего использования в Django используется доступ к атрибутам.

Например, если вы используете AuthenticationMiddleware и хотите узнать, вошел ли пользователь в систему в данный момент, вы должны использовать:

if request.user.is_authenticated:
    ...  # Do something for logged-in users.
else:
    ...  # Do something for anonymous users.

вместо request.user.is_authenticated().

Это изменение позволяет избежать случайной утечки информации, если вы забудете вызвать метод, например:

if request.user.is_authenticated:
    return sensitive_information

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

Django использует объект CallableBool, чтобы позволить этим атрибутам работать и как свойство, и как метод. Таким образом, пока не закончится период устаревания, вы не сможете сравнивать эти свойства с помощью оператора is. То есть следующее не будет работать:

if request.user.is_authenticated is True:
    ...

«Эскейп-половина» django.utils.safestring``

Функция mark_for_escaping() и используемые ею классы: EscapeData, EscapeBytes, EscapeText, EscapeString и EscapeUnicode считаются устаревшими.

В результате «ленивое» поведение фильтра escape (когда он всегда применялся как последний фильтр, независимо от того, где в цепочке фильтров он появлялся) считается устаревшим. Фильтр изменится и немедленно применит conditional_escape() в Django 2.0.

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

  • Опция makemigrations –exit устарела в пользу опции makemigrations --check.

  • django.utils.functional.allow_lazy() устарел в пользу новой функции keep_lazy(), которую можно использовать с более естественным синтаксисом декоратора.

  • Опция shell --plain устарела в пользу -i python или --interface python.

  • Импорт из модуля django.core.urlresolvers устарел в пользу его нового местоположения, django.urls.

  • Шаблонный метод Context.has_key() устарел в пользу метода in.

  • Частный атрибут virtual_fields в Model._meta устарел в пользу private_fields.

  • Аргументы частного ключевого слова virtual_only в Field.contribute_to_class() и virtual в Model._meta.add_field() устарели в пользу private_only и private соответственно.

  • Представления javascript_catalog() и json_catalog() устарели в пользу представлений на основе классов JavaScriptCatalog и JSONCatalog.

  • При многотабличном наследовании неявное повышение OneToOneField до родительской ссылки считается устаревшим. Добавьте в такие поля parent_link=True.

  • Частный API Widget._format_value() стал общедоступным и переименован в format_value(). Старое имя будет действовать в течение периода устаревания.

  • Частные методы FileField get_directory_name() и get_filename() устарели в пользу выполнения этой работы в Storage.generate_filename()).

  • Промежуточное программное обеспечение старого типа, использующее settings.MIDDLEWARE_CLASSES, считается устаревшим. Адаптируйте старое пользовательское промежуточное ПО и используйте новый параметр MIDDLEWARE.

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

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

  • Поддержка вызова SQLCompiler напрямую в качестве псевдонима для вызова его метода quote_name_unless_alias удалена.

  • Теги шаблонов cycle и firstof удалены из библиотеки тегов шаблонов future.

  • django.conf.urls.patterns() удален.

  • Поддержка аргумента prefix для django.conf.urls.i18n.i18n_patterns() удалена.

  • SimpleTestCase.urls удален.

  • Использование неправильного количества распакованных значений в теге шаблона for вызывает исключение, а не сбой без уведомления.

  • Удалена возможность reverse() URL-адресов с использованием точечного пути Python.

  • Возможность использовать пунктирный путь Python для настроек LOGIN_URL и LOGIN_REDIRECT_URL удалена.

  • Поддержка optparse прекращена для пользовательских команд управления.

  • Класс django.core.management.NoArgsCommand удален.

  • Модуль django.core.context_processors удален.

  • Модуль django.db.models.sql.aggregates удален.

  • Модуль django.contrib.gis.db.models.sql.aggregates удален.

  • Следующие методы и свойства django.db.sql.query.Query удалены:

    • Свойства: агрегаты и aggregate_select

    • Методы: add_aggregate, set_aggregate_mask иappend_aggregate_mask.

  • django.template.resolve_variable удален.

  • Следующие частные API удалены из django.db.models.options.Options (Model._meta):

    • get_field_by_name()

    • get_all_field_names()

    • get_fields_with_model()

    • get_concrete_fields_with_model()

    • get_m2m_with_model()

    • get_all_related_objects()

    • get_all_related_objects_with_model()

    • get_all_lated_many_to_many_objects()

    • get_all_lated_m2m_objects_with_model()

  • Аргумент error_message файла django.forms.RegexField удален.

  • Фильтр unordered_list больше не поддерживает списки старого стиля.

  • Поддержка строковых аргументов view для url() удалена.

  • Обратная совместимая оболочка для переименования django.forms.Form._has_changed() в has_changed() удалена.

  • Фильтр шаблона removetags удален.

  • Функции remove_tags() и strip_entities() в django.utils.html удалены.

  • Аргумент is_admin_site для django.contrib.auth.views.password_reset() удален.

  • django.db.models.field.subclassing.SubfieldBase удален.

  • django.utils.checksums удален.

  • Атрибут original_content_type_id в django.contrib.admin.helpers.InlineAdminForm удален.

  • Оболочка обратной совместимости, позволяющая определять FormMixin.get_form() без значения по умолчанию для аргумента form_class, удалена.

  • Следующие настройки будут удалены, и вам необходимо обновить настройку до настройки TEMPLATES:

    • ALLOWED_INCLUDE_ROOTS

    • TEMPLATE_CONTEXT_PROCESSORS

    • TEMPLATE_DEBUG

    • TEMPLATE_DIRS

    • TEMPLATE_LOADERS

    • TEMPLATE_STRING_IF_INVALID

  • Псевдоним обратной совместимости django.template.loader.BaseLoader удален.

  • Объекты шаблона Django, возвращаемые get_template() и select_template(), больше не принимают Context в своем методе render().

  • API ответа шаблона обеспечивают использование dict и объектов шаблонов, зависящих от серверной части, вместо Context и Template соответственно.

  • Параметр current_app для следующей функции и классов удален:

    • django.shortcuts.render()

    • django.template.Context()

    • django.template.RequestContext()

    • django.template.response.TemplateResponse()

  • Параметры dictionary и context_instance для следующих функций удалены:

    • django.shortcuts.render()

    • django.shortcuts.render_to_response()

    • django.template.loader.render_to_string()

  • Параметр dirs для следующих функций удален:

    • django.template.loader.get_template()

    • django.template.loader.select_template()

    • django.shortcuts.render()

    • django.shortcuts.render_to_response()

  • Проверка сеанса включена независимо от того, находится ли 'django.contrib.auth.middleware.SessionAuthenticationMiddleware' в MIDDLEWARE_CLASSES. SessionAuthenticationMiddleware больше не имеет никакого назначения и может быть удален из MIDDLEWARE_CLASSES. До Django 2.0 он хранится как заглушка для удобства пользователей, которые не читают эту заметку.

  • Частный атрибут django.db.models.Field.related удален.

  • Опция --list команды управления migrate удалена.

  • Тег шаблона ssi удален.

  • Поддержка оператора сравнения = в теге шаблона if удалена.

  • Прокладки обратной совместимости, позволяющие определять Storage.get_available_name() и Storage.save() без аргумента max_length, удалены.

  • Поддержка устаревшего синтаксиса %(<foo>)s в ModelFormMixin.success_url удалена.

  • Агрегатные методы GeoQuerySet``collect(), extent(), extent3d(), make_line() и unionagg() удалены.

  • Возможность указать «ContentType.name» при создании экземпляра типа контента удалена.

  • Поддержка старой подписи allow_migrate удалена.

  • Удалена поддержка синтаксиса {% Cycle %}, который использует аргументы, разделенные запятыми.

  • Предупреждение, которое Signer выдает при указании недопустимого разделителя, теперь является ValueError.

Back to Top