2019 年 4 月 1 日
欢迎使用 Django 2.2 !
这些发布说明涵盖了 新功能,以及在从 Django 2.1 或更早版本升级时需要注意的一些 向后不兼容的更改。我们已经 开始了一些功能的弃用过程。
如果你要更新现有的项目,请看 如何将 Django 更新至新的版本 指南。
Django 2.2 被指定为 长期支持版本。它将在发布后至少三年内接收安全更新。对于之前的 LTS 版本 Django 1.11,支持将在 2020 年 4 月结束。
Django 2.2 支持 Python 3.5、3.6、3.7、3.8(从 2.2.8 版开始),以及 3.9(从 2.2.17 版开始)。我们 强烈建议 并只官方支持每个系列的最新版本。
新的 CheckConstraint
和 UniqueConstraint
类允许添加自定义数据库约束。约束可以使用 Meta.constraints
选项添加到模型中。
django.contrib.admin
¶为 TabularInline
的列标题添加了一个 CSS 类。
django.contrib.auth
¶如果接受,现在将 HttpRequest
作为 RemoteUserBackend.configure_user()
的第一个位置参数传递。
django.contrib.gis
¶django.contrib.postgres
¶新的 BTreeIndex
、HashIndex
和 SpGistIndex
类允许在数据库中创建 B-Tree
、hash
和 SP-GiST
索引。
BrinIndex
现在具有 autosummarize
参数。
SearchQuery
的新参数 search_type
允许搜索短语或原始表达式。
django.contrib.staticfiles
¶在 collectstatic --ignore
选项中添加了路径匹配功能,以便可以使用像 /vendor/*.js
这样的模式。
在 SQLite 上为 QuerySet.iterator()
添加了结果流式传输功能。
新的 View.setup
钩子在调用 dispatch()
之前初始化视图属性。它允许 mixins 设置实例属性,以便在子类中重用。
增加了对亚美尼亚语的支持和翻译。
新的 --force-color
选项强制对命令输出进行着色。
inspectdb
现在会为 PostgreSQL 上的外部表创建模型。
inspectdb --include-views
现在会为 Oracle 和 PostgreSQL 上的物化视图创建模型。
新的 inspectdb --include-partitions
选项允许在 PostgreSQL 上为分区表创建模型。在旧版本中,模型是在子表而不是父表中创建的。
inspectdb
现在可以为 Oracle 和 PostgreSQL 自动检测 DurationField
,以及为 SQLite 检测 AutoField
。
在 Oracle 上,如果可用,dbshell
会使用 rlwrap
包装。rlwrap
提供了命令历史记录和键盘输入的编辑功能。
新的 makemigrations --no-header
选项可以避免在生成的迁移文件中写入头部注释。这个选项也适用于 squashmigrations
。
新的 migrate --plan
选项会打印将执行的迁移操作列表。
NoneType
现在可以在迁移中序列化。
现在可以为迁移 注册自定义序列化程序。
添加了对 PostgreSQL 运算符类 (Index.opclasses
) 的支持。
添加了对部分索引 (Index.condition
) 的支持。
将 QuerySet.bulk_create()
的新参数 ignore_conflicts
设置为 True
会告诉数据库忽略插入失败的行,即违反唯一性约束或其他检查的行。
新的 ExtractIsoYear
函数从 DateField
和 DateTimeField
中提取 ISO-8601 周编号年,新的 iso_year
查询允许按 ISO-8601 周编号年进行查询。
新的 QuerySet.bulk_update()
方法允许高效地更新多个模型实例上的特定字段。
Django 不再总是在执行单个查询时启动事务,例如 Model.save()
, QuerySet.update()
和 Model.delete()
。这通过减少数据库往返次数来提高自动提交的性能。
对于 Aggregate
类,增加了 DISTINCT
聚合的处理。在 Aggregate
子类上添加 allow_distinct = True
作为类属性,允许在初始化时指定一个 distinct
关键字参数,以确保聚合函数仅对 expressions
的每个不同值调用一次。
现在允许在具有中间模型的多对多关系上使用 RelatedManager.add()
、create()
、remove()
、set()
、get_or_create()
和 update_or_create()
方法。新的 through_defaults
参数用于指定新中间模型实例的值。
添加了 HttpRequest.headers
,以便简单访问请求的头部信息。
新的 SimpleTestCase.assertURLEqual()
断言检查给定的 URL,忽略查询字符串的顺序。assertRedirects()
使用了这个新的断言。
现在,测试 Client
在 content_type='application/json'
时支持自动对列表和元组 data
进行 JSON 序列化。
新的 ORACLE_MANAGED_FILES
测试数据库设置允许使用 Oracle 管理文件 (OMF) 表空间。
可延迟的数据库约束现在在 SQLite 3.20+ 上的每个 TestCase
测试结束时进行检查,就像其他支持可延迟约束的后端一样。对于较旧版本的 SQLite,这些检查没有实现,因为在那里需要昂贵的表内省。
DiscoverRunner
现在会跳过未被 测试引用 的数据库的设置。
新的 ResolverMatch.route
属性存储匹配的 URL 模式的路由。
MaxValueValidator
、MinValueValidator
、MinLengthValidator
和 MaxLengthValidator
现在接受可调用的 limit_value
。
本节介绍了第三方数据库后端可能需要的更改。
第三方数据库后端必须实现对表检查约束的支持,或将 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.ConcreteModel
的 app.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 上,PositiveIntegerField
和 PositiveSmallIntegerField
现在包含一个检查约束,以防止在数据库中出现负值。如果您有现有的无效数据并运行重新创建表的迁移,您将看到 CHECK constraint failed
。
为了与 WSGI 服务器保持一致,测试客户端现在将 Content-Length
头设置为字符串而不是整数。
django.utils.text.slugify()
的返回值不再标记为 HTML 安全。
urlizetrunc
、truncatechars
、truncatechars_html
、truncatewords
和 truncatewords_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>
的值为 unknown
、true
和 false
,而不是 1
、2
和 3
。为了向后兼容,旧值仍然被接受为数据。
Group.name
的 max_length
从 80 增加到 150 个字符。
现在在运行于 SQLite 3.20+ 上的测试中,违反可延迟数据库约束的行为将报错,就像其他支持此类约束的后端一样。
为了捕获使用错误,测试 Client
和 django.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
时, Avg
、StdDev
和 Variance
聚合函数现在返回 Decimal
而不是 float
。
如果没有迁移的应用与具有迁移的应用有关系,那么在 SQLite 上的测试将失败。这自从 Django 1.7 添加迁移以来一直是一个已记录的限制,但现在它失败得更可靠。您将看到类似于 no such table: <app_label>_<model>
的错误导致测试失败。这在一些具有测试中没有迁移的模型的第三方应用中观察到。您必须为这些模型添加迁移。
在 cache.delete()
或 cache.get()
的 key
参数中提供整数现在会引发 ValueError
。
由于已纳入 Transifex 的最新版本,某些语言的复数规则方程式已被更改。
Note
在 Django 2.2.12 中添加了处理同一语言的 .po
文件中包含不同复数方程的能力。
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_queries
、TransactionTestCase.multi_db
和 TestCase.multi_db
属性已被弃用,推荐使用 SimpleTestCase.databases
、TransactionTestCase.databases
和 TestCase.databases
。这些新属性允许声明数据库依赖关系,以防止非默认数据库的意外查询在测试之间泄漏状态。以前的行为可以通过设置 databases='__all__'
来实现,即 allow_database_queries=True
和 multi_db=True
。
4月 27, 2025