Django 2.2 版本发行说明

2019 年 4 月 1 日

欢迎使用 Django 2.2 !

这些发布说明涵盖了 新功能,以及在从 Django 2.1 或更早版本升级时需要注意的一些 向后不兼容的更改。我们已经 开始了一些功能的弃用过程

如果你要更新现有的项目,请看 如何将 Django 更新至新的版本 指南。

Django 2.2 被指定为 长期支持版本。它将在发布后至少三年内接收安全更新。对于之前的 LTS 版本 Django 1.11,支持将在 2020 年 4 月结束。

Python 兼容性

Django 2.2 支持 Python 3.5、3.6、3.7、3.8(从 2.2.8 版开始),以及 3.9(从 2.2.17 版开始)。我们 强烈建议 并只官方支持每个系列的最新版本。

Django 2.2 的新功能有哪些呢?

约束

新的 CheckConstraintUniqueConstraint 类允许添加自定义数据库约束。约束可以使用 Meta.constraints 选项添加到模型中。

次要特性

django.contrib.admin

django.contrib.auth

django.contrib.gis

  • Envelope 函数添加了对 Oracle 数据库的支持。
  • coveredbycovers 查询添加了对 SpatiaLite 的支持。

django.contrib.postgres

django.contrib.staticfiles

  • collectstatic --ignore 选项中添加了路径匹配功能,以便可以使用像 /vendor/*.js 这样的模式。

数据库后端

通用视图

  • 新的 View.setup 钩子在调用 dispatch() 之前初始化视图属性。它允许 mixins 设置实例属性,以便在子类中重用。

国际化

  • 增加了对亚美尼亚语的支持和翻译。

管理命令

迁移

模型

  • 添加了对 PostgreSQL 运算符类 (Index.opclasses) 的支持。
  • 添加了对部分索引 (Index.condition) 的支持。
  • 添加了 NullIfReverse 数据库函数,以及许多 数学数据库函数
  • QuerySet.bulk_create() 的新参数 ignore_conflicts 设置为 True 会告诉数据库忽略插入失败的行,即违反唯一性约束或其他检查的行。
  • 新的 ExtractIsoYear 函数从 DateFieldDateTimeField 中提取 ISO-8601 周编号年,新的 iso_year 查询允许按 ISO-8601 周编号年进行查询。
  • 新的 QuerySet.bulk_update() 方法允许高效地更新多个模型实例上的特定字段。
  • Django 不再总是在执行单个查询时启动事务,例如 Model.save(), QuerySet.update()Model.delete()。这通过减少数据库往返次数来提高自动提交的性能。
  • StdDevVariance 函数添加了 SQLite 支持。
  • 对于 Aggregate 类,增加了 DISTINCT 聚合的处理。在 Aggregate 子类上添加 allow_distinct = True 作为类属性,允许在初始化时指定一个 distinct 关键字参数,以确保聚合函数仅对 expressions 的每个不同值调用一次。
  • 现在允许在具有中间模型的多对多关系上使用 RelatedManager.add()create()remove()set()get_or_create()update_or_create() 方法。新的 through_defaults 参数用于指定新中间模型实例的值。

请求和响应

序列化

  • 现在可以通过将 handle_forward_references=True 传递给 serializers.deserialize() 来使用包含 前向引用 的自然键反序列化数据。此外,loaddata 现在会自动处理前向引用。

测试

  • 新的 SimpleTestCase.assertURLEqual() 断言检查给定的 URL,忽略查询字符串的顺序。assertRedirects() 使用了这个新的断言。
  • 现在,测试 Clientcontent_type='application/json' 时支持自动对列表和元组 data 进行 JSON 序列化。
  • 新的 ORACLE_MANAGED_FILES 测试数据库设置允许使用 Oracle 管理文件 (OMF) 表空间。
  • 可延迟的数据库约束现在在 SQLite 3.20+ 上的每个 TestCase 测试结束时进行检查,就像其他支持可延迟约束的后端一样。对于较旧版本的 SQLite,这些检查没有实现,因为在那里需要昂贵的表内省。
  • DiscoverRunner 现在会跳过未被测试引用的数据库的设置。

URLs

验证器

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"))

代理模型的权限

代理模型的权限 现在使用代理模型的内容类型而不是具体模型的内容类型来创建。在运行 migrate 时,迁移将更新现有的权限。

在管理界面中,对于与其具体模型具有相同的 app_label 的代理模型,这个变化是透明的。然而,在旧版本中,对于具体模型具有不同 app_label 的代理模型的权限的用户不能访问管理中的模型。现在这个问题已经修复,但在升级之前,您可能希望审查这些代理模型的权限分配([add|view|change|delete]_myproxy),以确保新的访问是合适的。

最后,代理模型的权限字符串必须更新以使用它们自己的 app_label。例如,对于继承自 other_app.ConcreteModelapp.MyProxyModel,请将 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', ...]

杂项

  • 为了提高可读性,UUIDField 表单字段现在会显示带有破折号的值,例如 550e8400-e29b-41d4-a716-446655440000,而不是 550e8400e29b41d4a716446655440000

  • 在 SQLite 上,PositiveIntegerFieldPositiveSmallIntegerField 现在包含一个检查约束,以防止在数据库中出现负值。如果您有现有的无效数据并运行重新创建表的迁移,您将看到 CHECK constraint failed

  • 为了与 WSGI 服务器保持一致,测试客户端现在将 Content-Length 头设置为字符串而不是整数。

  • django.utils.text.slugify() 的返回值不再标记为 HTML 安全。

  • urlizetrunctruncatecharstruncatechars_htmltruncatewordstruncatewords_html 模板过滤器使用的默认截断字符现在是真正的省略号字符()而不是 3 个点。您可能需要调整一些测试输出的比较。

  • 不再支持在模板文件系统加载器中使用字节串路径。

  • 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> 的值为 unknowntruefalse,而不是 123。为了向后兼容,旧值仍然被接受为数据。

  • Group.namemax_length 从 80 增加到 150 个字符。

  • 现在在运行于 SQLite 3.20+ 上的测试中,违反可延迟数据库约束的行为将报错,就像其他支持此类约束的后端一样。

  • 为了捕获使用错误,测试 Clientdjango.utils.http.urlencode() 现在如果传递 None 作为要编码的值会引发 TypeError,因为 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 替代)。

  • 当输入是 Decimal 时, AvgStdDevVariance 聚合函数现在返回 Decimal 而不是 float

  • 如果没有迁移的应用与具有迁移的应用有关系,那么在 SQLite 上的测试将失败。这自从 Django 1.7 添加迁移以来一直是一个已记录的限制,但现在它失败得更可靠。您将看到类似于 no such table: <app_label>_<model> 的错误导致测试失败。这在一些具有测试中没有迁移的模型的第三方应用中观察到。您必须为这些模型添加迁移。

  • cache.delete()cache.get()key 参数中提供整数现在会引发 ValueError

  • 由于已纳入 Transifex 的最新版本,某些语言的复数规则方程式已被更改。

    备注

    在 Django 2.2.12 中添加了处理同一语言的 .po 文件中包含不同复数方程的能力。

在 2.2 中被废弃的功能

模型的 Meta.ordering 将不再影响 GROUP BY 查询。

模型的 Meta.ordering 影响 GROUP BY 查询(例如 .annotate().values())是常见的引发混淆的原因。现在,这种查询会发出一个弃用警告,建议添加一个 order_by() 以保留当前查询。从 Django 3.1 开始,在这种查询中将忽略 Meta.ordering

杂项

  • django.utils.timezone.FixedOffset 已被弃用,建议使用 datetime.timezone
  • 未记录的 QuerySetPaginator 别名 django.core.paginator.Paginator 已被弃用。
  • django.contrib.postgres 中的 FloatRangeField 模型和表单字段已被弃用,推荐使用新名称 DecimalRangeField,以匹配数据库中使用的 numrange 数据类型。
  • FILE_CHARSET 设置已被弃用。从 Django 3.1 开始,从磁盘读取的文件必须是 UTF-8 编码的。
  • django.contrib.staticfiles.storage.CachedStaticFilesStorage 已被弃用,因为它存在无法解决的问题。请改用 ManifestStaticFilesStorage 或第三方云存储。
  • 现在,RemoteUserBackend.configure_user() 方法的第一个位置参数是 request,如果该方法接受它的话。不支持不接受 request 参数的覆盖方法,将在 Django 3.1 中移除。
  • SimpleTestCase.allow_database_queriesTransactionTestCase.multi_dbTestCase.multi_db 属性已被弃用,推荐使用 SimpleTestCase.databasesTransactionTestCase.databasesTestCase.databases。这些新属性允许声明数据库依赖关系,以防止非默认数据库的意外查询在测试之间泄漏状态。以前的行为可以通过设置 databases='__all__' 来实现,即 allow_database_queries=Truemulti_db=True
Back to Top