Примечания к выпуску Django 2.2¶
1 апреля 2019 года
Добро пожаловать в Django 2.2!
Эти заметки о выпуске охватывают new features, а также некоторые backwards incompatible changes, о которых вы должны знать при переходе с Django 2.1 или более ранней версии. Мы begun the deprecation process for some features.
См. руководство Как обновить Django до более новой версии, если вы обновляете существующий проект.
Django 2.2 обозначен как long-term support release. Она будет получать обновления безопасности в течение как минимум трех лет после выпуска. Поддержка предыдущей LTS, Django 1.11, закончится в апреле 2020 года.
Совместимость с Python¶
Django 2.2 поддерживает Python 3.5, 3.6, 3.7, 3.8 (начиная с 2.2.8) и 3.9 (начиная с 2.2.17). Мы настоятельно рекомендуем и официально поддерживаем только последний выпуск каждой серии.
Что нового в Django 2.2¶
Ограничения¶
Новые классы CheckConstraint и UniqueConstraint позволяют добавлять пользовательские ограничения базы данных. Ограничения добавляются в модели с помощью опции Meta.constraints.
Незначительные особенности¶
django.contrib.admin¶
- Добавлен CSS-класс для заголовков столбцов 
TabularInline. 
django.contrib.auth¶
- Теперь 
HttpRequestпередается как первый позиционный аргумент вRemoteUserBackend.configure_user(), если он его принимает. 
django.contrib.postgres¶
- Новый аргумент 
orderingдляArrayAggиStringAggопределяет порядок следования агрегированных элементов. - Новые классы 
BTreeIndex,HashIndexиSpGistIndexпозволяют создавать индексыB-Tree,hashиSP-GiSTв базе данных. BrinIndexтеперь имеет параметрautosummarize.- Новый параметр 
search_typeвSearchQueryпозволяет искать по фразе или необработанному выражению. 
django.contrib.staticfiles¶
- В опцию 
collectstatic --ignoreдобавлено сопоставление путей, чтобы можно было использовать шаблоны типа/vendor/*.js. 
Бэкенды баз данных¶
- Добавлена потоковая передача результатов для 
QuerySet.iterator()на SQLite. 
Общие представления¶
- Новый хук 
View.setupинициализирует атрибуты представления перед вызовомdispatch(). Это позволяет миксинам настраивать атрибуты экземпляра для повторного использования в дочерних классах. 
Интернационализация¶
- Добавлена поддержка и переводы для армянского языка.
 
Команды управления¶
- Новая опция 
--force-colorпринудительно окрашивает вывод команды. inspectdbтеперь создает модели для иностранных таблиц на PostgreSQL.inspectdb --include-viewsтеперь создает модели для материализованных представлений на Oracle и PostgreSQL.- Новая опция 
inspectdb --include-partitionsпозволяет создавать модели для таблиц разделов на PostgreSQL. В старых версиях модели создавались дочерними таблицами вместо родительской. inspectdbтеперь интроспекцияDurationFieldдля Oracle и PostgreSQL, иAutoFieldдля SQLite.- В Oracle 
dbshellоборачиваетсяrlwrap, если доступно.rlwrapпредоставляет историю команд и редактирование ввода с клавиатуры. - Новая опция 
makemigrations --no-headerпозволяет избежать записи комментариев к заголовкам в сгенерированный файл(ы) миграции. Эта опция также доступна дляsquashmigrations. runserverтеперь может использовать Watchman для повышения производительности при просмотре большого количества файлов на предмет изменений.
Миграции¶
- Новая опция 
migrate --planвыводит список операций миграции, которые будут выполнены. NoneTypeтеперь можно сериализовать в миграциях.- Теперь вы можете register custom serializers для миграций.
 
Модели¶
- Добавлена поддержка классов операторов PostgreSQL (
Index.opclasses). - Добавлена поддержка частичных индексов (
Index.condition). - Добавлены функции базы данных 
NullIfиReverse, а также множество math database functions. - Установка нового параметра 
ignore_conflictsизQuerySet.bulk_create()вTrueуказывает базе данных игнорировать отказ вставки строк, которые не проходят ограничения уникальности или другие проверки. - Новая функция 
ExtractIsoYearизвлекает годы недели по ISO-8601 изDateFieldиDateTimeField, а новый поискiso_yearпозволяет выполнять запрос по году недели по ISO-8601. - Новый метод 
QuerySet.bulk_update()позволяет эффективно обновлять определенные поля на нескольких экземплярах модели. - Django больше не всегда начинает транзакцию при выполнении одного запроса, например, 
Model.save(),QuerySet.update()иModel.delete(). Это улучшает производительность autocommit, уменьшая количество обходов базы данных. - Добавлена поддержка SQLite для функций 
StdDevиVariance. - Обработка агрегации 
DISTINCTдобавлена в классAggregate. Добавлениеallow_distinct = Trueв качестве атрибута класса для подклассовAggregateпозволяет указать аргумент ключевого словаdistinctпри инициализации, чтобы гарантировать, что агрегатная функция вызывается только для каждого отдельного значенияexpressions. - Методы 
RelatedManager.add(),create(),remove(),set(),get_or_create()иupdate_or_create()теперь разрешены для отношений «многие-ко-многим» с промежуточными моделями. Новый аргументthrough_defaultsиспользуется для указания значений для новых экземпляров промежуточных моделей. 
Запросы и ответы¶
- Добавлено 
HttpRequest.headersдля простого доступа к заголовкам запроса. 
Сериализация¶
- Теперь вы можете десериализовать данные, используя натуральные ключи, содержащие forward references, передавая 
handle_forward_references=Trueвserializers.deserialize(). Кроме того,loaddataавтоматически обрабатывает прямые ссылки. 
Тесты¶
- Новое утверждение 
SimpleTestCase.assertURLEqual()проверяет заданный URL, игнорируя порядок строки запроса.assertRedirects()использует новое утверждение. - Тест 
Clientтеперь поддерживает автоматическую JSON сериализацию списка и кортежаdataприcontent_type='application/json'. - Новая настройка тестовой базы данных 
ORACLE_MANAGED_FILESпозволяет использовать табличные пространства Oracle Managed Files (OMF). - Откладываемые ограничения базы данных теперь проверяются в конце каждого теста 
TestCaseна SQLite 3.20+, как и на других бэкендах, поддерживающих откладываемые ограничения. Эти проверки не реализованы для более старых версий SQLite, поскольку они потребовали бы дорогостоящего интроспекта таблиц. DiscoverRunnerтеперь пропускает настройку баз данных не referenced by tests.
URLs¶
- Новый атрибут 
ResolverMatch.routeхранит маршрут соответствующего шаблона URL. 
Валидаторы¶
MaxValueValidator,MinValueValidator,MinLengthValidatorиMaxLengthValidatorтеперь принимают вызываемыйlimit_value.
Изменения в версии 2.2, несовместимые с обратными изменениями¶
API бэкенда базы данных¶
В этом разделе описаны изменения, которые могут потребоваться в бэкендах баз данных сторонних производителей.
- Бэкенды баз данных сторонних производителей должны реализовать поддержку ограничений проверки таблиц или установить 
DatabaseFeatures.supports_table_check_constraintsвFalse. - Сторонние бэкенды баз данных должны реализовать поддержку игнорирования ограничений или ошибок уникальности при вставке или установке 
DatabaseFeatures.supports_ignore_conflictsвFalse. - Сторонние бэкенды баз данных должны реализовать интроспекцию для 
DurationFieldили установитьDatabaseFeatures.can_introspect_duration_fieldвFalse. DatabaseFeatures.uses_savepointsтеперь по умолчаниюTrue.- Сторонние бэкенды баз данных должны реализовать поддержку частичных индексов или установить 
DatabaseFeatures.supports_partial_indexesнаFalse. DatabaseIntrospection.table_name_converter()иcolumn_name_converter()удалены. Сторонним бэкендам баз данных может понадобиться вместо этого реализоватьDatabaseIntrospection.identifier_converter(). В этом случае имена ограничений, которые возвращаетDatabaseIntrospection.get_constraints(), должны быть нормализованы с помощьюidentifier_converter().- Генерация SQL для индексов перенесена с 
IndexнаSchemaEditorи добавлены эти методыSchemaEditor:_create_primary_key_sql()и_delete_primary_key_sql()_delete_index_sql()(в паре с_create_index_sql())_delete_unique_sql(в паре с_create_unique_sql())_delete_fk_sql()(в паре с_create_fk_sql())_create_check_sql()и_delete_check_sql()
 - Третий аргумент 
DatabaseWrapper.__init__(),allow_thread_sharing, удаляется. 
Действия администратора больше не собираются из базовых классов ModelAdmin¶
Например, в старых версиях Django:
from django.contrib import admin
class BaseAdmin(admin.ModelAdmin):
    actions = ["a"]
class SubAdmin(BaseAdmin):
    actions = ["b"]
SubAdmin будет иметь действия 'a' и 'b'.
Теперь actions следует стандартному наследованию Python. Чтобы получить тот же результат, что и раньше:
class SubAdmin(BaseAdmin):
    actions = BaseAdmin.actions + ["b"]
django.contrib.gis¶
- Поддержка GDAL 1.9 и 1.10 прекращена.
 
TransactionTestCase загрузка сериализованных данных¶
Начальные миграции данных теперь загружаются в TransactionTestCase в конце теста, после промывки базы данных. В старых версиях эти данные загружались в начале теста, но это не позволяло опции test --keepdb работать правильно (база данных была пустой в конце всего набора тестов). Это изменение не должно повлиять на ваши тесты, если только вы не изменили внутреннее устройство TransactionTestCase.
sqlparse является необходимой зависимостью¶
Чтобы упростить некоторые моменты работы Django с базами данных, sqlparse 0.2.2+ теперь является обязательной зависимостью. Она автоматически устанавливается вместе с Django.
cached_property псевдонимы¶
В использовании, например:
from django.utils.functional import cached_property
class A:
    @cached_property
    def base(self):
        return ...
    alias = base
alias не кэшируется. Там, где проблема может быть обнаружена (Python 3.6 и более поздние версии), такое использование теперь вызывает ошибку TypeError: Cannot assign the same cached_property to two different names ('base' and 'alias').
Вместо этого используйте следующее:
import operator
class A:
    ...
    alias = property(operator.attrgetter("base"))
Разрешения для прокси-моделей¶
Permissions for proxy models теперь создаются с использованием типа содержимого прокси-модели, а не типа содержимого конкретной модели. При миграции существующие разрешения будут обновлены при запуске migrate.
В админке это изменение прозрачно для прокси-моделей, имеющих тот же app_label, что и их конкретная модель. Однако в старых версиях пользователи с правами на прокси-модель с отличным app_label, чем у ее конкретной модели, не могли получить доступ к модели в админке. Теперь это исправлено, но вы, возможно, захотите проверить назначения прав для таких прокси-моделей ([add|view|change|delete]_myproxy) перед обновлением, чтобы убедиться, что новый доступ соответствует требованиям.
Наконец, строки разрешений прокси-модели должны быть обновлены, чтобы использовать свои собственные app_label. Например, для app.MyProxyModel, наследующего от other_app.ConcreteModel, обновите user.has_perm('other_app.add_myproxymodel') до user.has_perm('app.add_myproxymodel').
Слияние активов формы Media¶
Активы формы Media теперь объединяются с помощью алгоритма топологической сортировки, так как старый алгоритм попарного объединения недостаточен для некоторых случаев. Файлы CSS и JavaScript, не включающие свои зависимости, теперь могут быть отсортированы неправильно (там, где старый алгоритм по совпадению выдавал правильные результаты).
Проверьте все классы Media на наличие отсутствующих зависимостей. Например, виджеты, зависящие от django.jQuery, должны указывать js=['admin/js/jquery.init.js', ...] при declaring form media assets.
Разное¶
Для улучшения читабельности поле формы
UUIDFieldтеперь отображает значения с тире, например,550e8400-e29b-41d4-a716-446655440000вместо550e8400e29b41d4a716446655440000.На SQLite,
PositiveIntegerFieldиPositiveSmallIntegerFieldтеперь включают проверочное ограничение для предотвращения отрицательных значений в базе данных. Если у вас есть недопустимые данные и вы запустили миграцию, которая воссоздает таблицу, вы увидитеCHECK constraint failed.Для согласованности с серверами WSGI тестовый клиент теперь устанавливает заголовок
Content-Lengthв строку, а не в целое число.Возвращаемое значение
django.utils.text.slugify()больше не помечается как HTML-безопасное.Символ усечения, используемый по умолчанию фильтрами шаблонов
urlizetrunc,truncatechars,truncatechars_html,truncatewordsиtruncatewords_html, теперь представляет собой настоящий символ многоточия (…) вместо трех точек. Возможно, вам придется адаптировать некоторые тестовые сравнения вывода.Устранена поддержка байтовых путей в загрузчике файловой системы шаблона.
django.utils.http.urlsafe_base64_encode()теперь возвращает строку, а не байтстринг, аdjango.utils.http.urlsafe_base64_decode()больше не может передаваться байтстринг.Удалена поддержка
cx_Oracle< 6.0.Минимальная поддерживаемая версия
mysqlclientувеличена с 1.3.7 до 1.3.13.Минимальная поддерживаемая версия SQLite увеличена с 3.7.15 до 3.8.3.
В попытке обеспечить более семантические данные запроса,
NullBooleanSelectтеперь отображает<option>значенияunknown,trueиfalseвместо1,2и3. Для обратной совместимости старые значения по-прежнему принимаются в качестве данных.Group.namemax_lengthувеличивается с 80 до 150 символов.Тесты, нарушающие откладываемые ограничения базы данных, теперь ошибаются при выполнении на SQLite 3.20+, как и на других бэкендах, поддерживающих такие ограничения.
Чтобы отловить ошибки использования, тесты
Clientиdjango.utils.http.urlencode()теперь поднимают вопросTypeError, если в качестве значения для кодирования передаетсяNone, посколькуNoneне может быть закодировано в данных GET и POST. Либо передайте пустую строку, либо опустите значение.Команда управления
ping_googleтеперь по умолчанию выбираетhttpsвместоhttpдля URL карты сайта. Если ваш сайт использует http, используйте новую опциюping_google --sitemap-uses-http. Если вы используете функциюdjango.contrib.sitemaps.ping_google, установите новый аргументsitemap_uses_httpsв значениеFalse.runserverбольше не поддерживаетpyinotify(заменен на Watchman).Агрегатные функции
Avg,StdDevиVarianceтеперь возвращаютDecimalвместоfloat, когда на вход подаетсяDecimal.Тесты не будут работать на SQLite, если приложения без миграций имеют отношения к приложениям с миграциями. Это было документированным ограничением с тех пор, как миграции были добавлены в Django 1.7, но теперь это происходит более надежно. Вы увидите, что тесты завершаются с ошибками типа
no such table: <app_label>_<model>. Это наблюдалось в нескольких сторонних приложениях, которые имели модели в тестах без миграций. Вы должны добавить миграции для таких моделей.Предоставление целого числа в аргументе
keyдляcache.delete()илиcache.get()теперь приводит к возникновениюValueError.Уравнения множественного числа для некоторых языков изменены, так как включены последние версии от Transifex.
Примечание
В Django 2.2.12 была добавлена возможность обрабатывать файлы
.po, содержащие различные множественные числа для одного и того же языка.
Функции, устаревшие в версии 2.2¶
Модель Meta.ordering больше не будет влиять на запросы GROUP BY¶
Запросы модели Meta.ordering, влияющие на запросы GROUP BY (такие как .annotate().values()), являются распространенным источником путаницы. Теперь такие запросы выдают предупреждение об устаревании с советом добавить order_by(), чтобы сохранить текущий запрос. Meta.ordering будет игнорироваться в таких запросах, начиная с Django 3.1.
Разное¶
django.utils.timezone.FixedOffsetустарел в пользуdatetime.timezone.- Недокументированный псевдоним 
QuerySetPaginatordjango.core.paginator.Paginatorявляется устаревшим. - Модель 
FloatRangeFieldи поля формыdjango.contrib.postgresустарели в пользу нового названияDecimalRangeField, чтобы соответствовать основному типу данныхnumrange, используемому в базе данных. - Параметр 
FILE_CHARSETустарел. Начиная с Django 3.1, файлы, считываемые с диска, должны быть в кодировке UTF-8. django.contrib.staticfiles.storage.CachedStaticFilesStorageявляется устаревшим из-за неразрешимых проблем. Вместо него используйтеManifestStaticFilesStorageили стороннее облачное хранилище.RemoteUserBackend.configure_user()теперь передаетсяrequestв качестве первого позиционного аргумента, если он его принимает. Поддержка переопределений, которые его не принимают, будет удалена в Django 3.1.- Атрибуты 
SimpleTestCase.allow_database_queries,TransactionTestCase.multi_dbиTestCase.multi_dbустарели в пользуSimpleTestCase.databases,TransactionTestCase.databasesиTestCase.databases. Эти новые атрибуты позволяют объявлять зависимости баз данных, чтобы предотвратить неожиданные запросы к базам данных не по умолчанию для утечки состояния между тестами. Прежнее поведениеallow_database_queries=Trueиmulti_db=Trueможет быть достигнуто установкойdatabases='__all__'.