Django 2.2 版本发行说明Link to this heading

2019 年 4 月 1 日

欢迎使用 Django 2.2 !

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

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

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

Python 兼容性Link to this heading

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

Django 2.2 的新功能有哪些呢?Link to this heading

约束Link to this heading

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

次要特性Link to this heading

django.contrib.adminLink to this heading

django.contrib.authLink to this heading

django.contrib.gisLink to this heading

  • Envelope 函数添加了对 Oracle 数据库的支持。

  • coveredbycovers 查询添加了对 SpatiaLite 的支持。

django.contrib.postgresLink to this heading

django.contrib.staticfilesLink to this heading

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

数据库后端Link to this heading

通用视图Link to this heading

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

国际化Link to this heading

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

管理命令Link to this heading

迁移Link to this heading

模型Link to this heading

  • 添加了对 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 参数用于指定新中间模型实例的值。

请求和响应Link to this heading

序列化Link to this heading

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

测试Link to this heading

  • 新的 SimpleTestCase.assertURLEqual() 断言检查给定的 URL,忽略查询字符串的顺序。assertRedirects() 使用了这个新的断言。

  • 现在,测试 Clientcontent_type='application/json' 时支持自动对列表和元组 data 进行 JSON 序列化。

  • 新的 ORACLE_MANAGED_FILES 测试数据库设置允许使用 Oracle 管理文件 (OMF) 表空间。

  • 可延迟的数据库约束现在在 SQLite 3.20+ 上的每个 TestCase 测试结束时进行检查,就像其他支持可延迟约束的后端一样。对于较旧版本的 SQLite,这些检查没有实现,因为在那里需要昂贵的表内省。

  • DiscoverRunner 现在会跳过未被 测试引用 的数据库的设置。

URLsLink to this heading

验证器Link to this heading

2.2 版本中的不向后兼容变更Link to this heading

数据库后端 APILink to this heading

本节介绍了第三方数据库后端可能需要的更改。

  • 第三方数据库后端必须实现对表检查约束的支持,或将 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 类中收集管理操作Link to this heading

例如,在较旧版本的 Django 中:

Code
from django.contrib import admin


class BaseAdmin(admin.ModelAdmin):
    actions = ["a"]


class SubAdmin(BaseAdmin):
    actions = ["b"]

SubAdmin 将具有操作 'a''b'

现在,actions 遵循标准的 Python 继承。要获得与以前相同的结果:

Code
class SubAdmin(BaseAdmin):
    actions = BaseAdmin.actions + ["b"]

django.contrib.gisLink to this heading

  • 支持 GDAL 1.9 和 1.10 的功能已被移除。

TransactionTestCase 序列化数据加载Link to this heading

现在,在 TransactionTestCase 的测试结束后,即在数据库刷新之后加载初始数据迁移。在旧版本中,这些数据在测试开始时加载,但这会阻止 test --keepdb 选项正常工作(整个测试套件结束后数据库为空)。除非您已自定义了 TransactionTestCase 的内部,否则这个变化不应影响您的测试。

sqlparse 是必需的依赖项Link to this heading

为了简化 Django 数据库处理的几个部分,现在 sqlparse 0.2.2+ 是一个必需的依赖项。它会随着 Django 自动安装。

cached_property 别名Link to this heading

在以下用法中:

Code
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')

请改用以下方式:

Code
import operator


class A:
    ...

    alias = property(operator.attrgetter("base"))

代理模型的权限Link to this heading

代理模型的权限 现在使用代理模型的内容类型而不是具体模型的内容类型来创建。在运行 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 资源Link to this heading

现在,表单 Media 资源使用拓扑排序算法进行合并,因为旧的成对合并算法对某些情况不足够。不包含其依赖项的 CSS 和 JavaScript 文件现在可能会被错误地排序(而旧算法恰好由于巧合而产生了正确的结果)。

请审查所有的 Media 类以查找任何缺失的依赖项。例如,依赖于 django.jQuery 的小部件在 声明表单媒体资源 时必须指定 js=['admin/js/jquery.init.js', ...]

杂项Link to this heading

  • 为了提高可读性,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 的最新版本,某些语言的复数规则方程式已被更改。

在 2.2 中被废弃的功能Link to this heading

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

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

杂项Link to this heading

  • 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