Django 3.2 版本发行说明
2021 年 4 月 6 日
欢迎来到 Django 3.2 版本!
这些发行说明涵盖了 新功能,以及一些 向后不兼容的变化,当你从 Django 3.1 或更早版本升级时,你需要注意。我们已经 开始了一些功能的废弃过程。
如果你要更新现有的项目,请看 如何将 Django 更新至新的版本 指南。
Django 3.2 被指定为 长期支持发行。它将在发行后至少三年内获得安全更新。对前一个 LTS,即 Django 2.2 的支持将于 2022 年 4 月结束。
Python 兼容性
Django 3.2 支持 Python 3.6、3.7、3.8、3.9 和 3.10(从 3.2.9 开始)。我们 高度推荐 并且只正式支持每个系列的最新版本。
Django 3.2 新特性
自动 AppConfig 发现
大多数可插拔的应用程序在 apps.py
子模块中定义一个 AppConfig 子类。许多人在他们的 __init__.py
中定义了一个 default_app_config
的变量,指向这个类。
当 apps.py
子模块存在并定义了一个 AppConfig 子类时,Django 现在自动使用该配置,所以你可以删除 default_app_config
。
default_app_config
使得在 INSTALLED_APPS 中只需声明应用程序的路径(例如 'django.contrib.admin'
)而不是应用程序配置的路径(例如 'django.contrib.admin.apps.AdminConfig'
)。它的引入是为了向后兼容前者的风格,目的是将生态系统切换到后者,但这种切换并没有发生。
随着自动发现 AppConfig
,default_app_config
不再需要了。因此,它被废弃了。
详见 配置应用程序。
自定义自动创建的主键的类型
当定义一个模型时,如果模型中没有字段被定义为 primary_key=True,则会添加一个隐式主键。这个隐式主键的类型现在可以通过 DEFAULT_AUTO_FIELD 设置和 AppConfig.default_auto_field 属性来控制。不再需要在所有模型中覆盖主键。
保持历史行为,DEFAULT_AUTO_FIELD 的默认值是 AutoField。从 3.2 开始,新项目在生成时,DEFAULT_AUTO_FIELD 设置为 BigAutoField。另外,新的应用程序生成时,AppConfig.default_auto_field 设置为 BigAutoField。在未来的 Django 版本中,DEFAULT_AUTO_FIELD 的默认值将被改为 BigAutoField。
为了避免将来不需要的迁移,要么明确设置 DEFAULT_AUTO_FIELD 为 AutoField :
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
或在每个应用的基础上进行配置:
from django.apps import AppConfig
class MyAppConfig(AppConfig):
default_auto_field = "django.db.models.AutoField"
name = "my_app"
或在每个模型的基础上:
from django.db import models
class MyModel(models.Model):
id = models.AutoField(primary_key=True)
由于预期默认值的变化,如果你没有明确设置 DEFAULT_AUTO_FIELD,系统检查将提供一个警告。
当改变 DEFAULT_AUTO_FIELD 的值时,目前不能生成现有的自动创建的表的主键的迁移。请参阅 DEFAULT_AUTO_FIELD 文档以了解迁移此类表的详情。
函数索引
新的 *expressions 的位置参数 Index() 能够在表达式和数据库函数上创建函数索引。例如:
from django.db import models
from django.db.models import F, Index, Value
from django.db.models.functions import Lower, Upper
class MyModel(models.Model):
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
height = models.IntegerField()
weight = models.IntegerField()
class Meta:
indexes = [
Index(
Lower("first_name"),
Upper("last_name").desc(),
name="first_last_name_idx",
),
Index(
F("height") / (F("weight") + Value(5)),
name="calc_idx",
),
]
函数索引是使用 Meta.indexes 选项添加到模型的。
pymemcache
支持
The new django.core.cache.backends.memcached.PyMemcacheCache
cache backend allows using the pymemcache library for memcached. pymemcache
3.4.0 or higher is required. For more details, see the documentation on caching in Django.
管理站点的新装饰器
新的 display() 装饰器允许轻松地为自定义显示函数添加选项,这些函数可以与 list_display 或 readonly_fields 一起使用。
同样,新的 action() 装饰器允许轻松地将选项添加到可与 actions 一起使用的动作函数。
使用 @display
装饰器的好处是,现在可以在需要指定自定义方法的属性时使用 @property
装饰器。在此之前,有必要在为方法指定所需的属性后使用 property()
函数来代替。
使用装饰器的好处是这些选项更容易被发现,因为它们可以被代码编辑器中的补全工具所提示。它们仅仅是一种方便,并且仍然在幕后的函数上设置相同的属性。
次要特性
django.contrib.admin
ModelAdmin.search_fields 现在允许针对带空格的引号短语进行搜索。
如果在管理中注册了目标模型,只读的相关字段现在被呈现为可浏览的链接。
管理现在支持主题化,包括一个根据浏览器配置启用的暗色主题。更多细节见 主题化支持。
ModelAdmin.autocomplete_fields 现在搜索一个相关模型时尊重 ForeignKey.to_field 和 ForeignKey.limit_choices_to。
管理现在安装了一个全局最终回退视图,将未经认证的用户重定向到登录页面,无论该 URL 是否有效。这可以防止潜在的模型枚举隐私问题。
尽管不推荐,你可以将新的 AdminSite.final_catch_all_view 设置为
False
来禁用所有视图。
django.contrib.auth
PBKDF2 密码散列器的默认迭代次数从 216,000 次增加到 260,000 次。
Argon2 密码散列器的默认变量改为 Argon2id。
memory_cost
和parallelism
分别增加到 102,400 和 8,以符合argon2-cffi
的默认值。增加
memory_cost
将所需的内存从 512KB 推到 100MB。这仍然是相当保守的,但在内存有限的环境中可能会导致问题。如果是这种情况,可以对现有的散列器进行子类化以覆盖默认值。Argon2, MD5, PBKDF2, SHA-1 密码散列器的默认盐熵从 71 位增加到 128 位。
django.contrib.contenttypes
- generic_inlineformset_factory() 的新参数
absolute_max
允许自定义提供POST
数据时可以实例化的最大表单数量。更多细节请参见 限制实例化表单的最大数量。 - generic_inlineformset_factory() 的新参数
can_delete_extra
允许移除删除额外表单的选项。更多信息请参见 can_delete_extra。
django.contrib.gis
- GDALRaster.transform() 方法现在支持 SpatialReference。
- DataSource 类现在支持 pathlib.Path。
- LayerMapping 类现在支持 pathlib.Path。
django.contrib.postgres
- 新的 ExclusionConstraint.include 属性允许在 PostgreSQL 12+ 上创建覆盖排除约束。
- The new
ExclusionConstraint.opclasses
attribute allows setting PostgreSQL operator classes. - 新的 JSONBAgg.ordering 属性决定了聚合元素的排序。
- 新的 JSONBAgg.distinct 属性决定了聚合的值是否会是唯一的。
- CreateExtension 操作现在会检查数据库中是否已经存在扩展,如果存在则跳过迁移过程。
- 新的 CreateCollation 和 RemoveCollation 操作允许在 PostgreSQL 上创建和删除排序。参见 使用迁移来管理整理 获取更多细节。
- 对 ArrayField 的查找现在允许包含表达式的(非嵌套)数组作为右侧。
- 新的 OpClass() 表达式允许在具有自定义运算符类的表达式上创建函数索引。参见 函数索引 获取更多细节。
django.contrib.sitemaps
- 新的 Sitemap 属性 alternates、languages 和 x_default 允许生成网站地图 替换为 你页面的本地化版本。
django.contrib.syndication
- 新的
item_comments
钩子允许为每个 feed 项目指定一个评论 URL。
数据库后端
- 第三方数据库后端现在可以使用新的
DatabaseFeatures.django_test_skips
和django_test_expected_failures
属性在 Django 测试套件中跳过或标记为预期失败的测试。
装饰器
- 新的 no_append_slash() 装饰器允许个别视图从 APPEND_SLASH URL 规范化中排除。
错误报告
- 自定义
ExceptionReporter
子类现在可以定义html_template_path
和text_template_path
属性来重写用于渲染异常报告的模板。
文件上传
- 新的 FileUploadHandler.upload_interrupted() 回调允许处理中断的上传。
表单
- formset_factory()、inlineformset_factory() 和 modelformset_factory() 的新
absolute_max
参数允许自定义提供POST
数据时可实例化的最大表单数量。参见 限制实例化表单的最大数量 以了解更多细节。 formet_factory()
、inlineformset_factory() 和 modelformset_factory() 的新参数can_delete_extra
允许删除额外的表单选项。更多信息请参见 can_delete_extra。- BaseFormSet 现在当管理表单丢失或被篡改时,会报告一个面向用户的错误,而不是引发一个异常。要自定义这个错误信息,请在实例化表单集时,将
error_messages
参数与'missing_management_form'
键一起传递。
通用视图
- WeekMixin 和 WeekArchiveView 的
week_format
属性现在支持'%V'
ISO 8601 星期格式。
管理命令
- loaddata 现在支持存储在 XZ 档案(.xz)和 LZMA 档案(.lzma)中的固定数据。
- dumpdata 现在可以压缩
bz2
、gz
、lzma
或xz
格式的数据。 - makemigrations 现在可以在没有数据库连接的情况下调用。在这种情况下,会跳过检查是否有一致的迁移历史。
BaseCommand.required_system_checks
现在支持指定一个标签列表。在所选标签中注册的系统检查将在执行命令前被检查出错误。在之前的版本中,所有的系统检查或者都不执行,或者都会被执行。- 更新了对 Windows 上彩色终端输出的支持。各种现代终端环境被自动检测到,在其他情况下启用支持的选项也被改进。更多细节见 语法着色。
迁移
- 新的
Operation.migration_name_fragment
属性允许提供一个文件名片段,该片段将被用来命名只包含该操作的迁移。 - 迁移现在支持从 pathlib 和 os.PathLike 实例中序列化纯路径和具体路径对象。
模型
- 在 PostgreSQL 上支持 QuerySet.select_for_update() 的新的
no_key
参数,允许获得较弱的锁,不会阻止创建通过外键引用被锁定行的新行。 - When() 表达式现在允许使用
condition
参数与lookups
。 - 新的 Index.include 和 UniqueConstraint.include 属性允许在 PostgreSQL 11+ 上创建覆盖索引和覆盖唯一约束。
- 新的 UniqueConstraint.opclasses 属性允许设置 PostgreSQL 操作符类。
- QuerySet.update() 方法现在尊重 MySQL 和 MariaDB 的
order_by()
子句。 - FilteredRelation() 现在支持嵌套关系。
- QuerySet.select_for_update() 的
of
参数现在于 MySQL 8.0.1+ 版本中被允许。 - Value() 表达式现在会根据其提供的
value
的类型自动将其output_field
解析为适当的 Field 子类,适用于 bool、bytes、float、int、str、datetime.date、datetime.datetime、datetime.time、datetime.timedelta、decimal.Decimal 和 uuid.UUID 实例。因此,在使用Value()
时,解析数据库函数和组合表达式的output_field
现在可能会因混合类型而崩溃。在这种情况下,你将需要明确地设置output_field
。 - 新的 QuerySet.alias() 方法允许为表达式创建可重复使用的别名,这些表达式不需要被选择,但可用于过滤、排序,或作为复杂表达式的一部分。
- 新的
Collate
函数允许通过指定的数据库排列方式进行过滤和排序。 - 如果在 QuerySet.distinct() 中只指定了一个字段,QuerySet.in_bulk() 的
field_name
参数现在可以接受不同的字段。 TruncDate
和TruncTime
数据库函数的新tzinfo
参数允许截断特定时区的数据时间。- 为 CharField 和 TextField 新增的
db_collation
参数允许为字段设置一个数据库排序。 - 添加了
Random
数据库函数。 - 聚合函数、F()、OuterRef() 以及其他表达式现在允许使用变换。详情参见 Expressions can reference transforms。
- atomic() 的新参数
durable
保证在原子块中所做的更改将被提交,如果该块退出时没有错误。嵌套的原子块被标记为耐用,将引发一个RuntimeError
。 - 添加了
JSONObject
数据库函数。
分页
- 新的 django.core.paginator.Paginator.get_elided_page_range() 方法允许生成一个页面范围,其中的一些值被删除。如果有大量的页面,这对在模板中生成合理数量的页面链接很有帮助。
请求和响应
- 响应头信息现在被存储在 HttpResponse.headers 中。这可以代替原来的
HttpResponse
对象的类似字典的接口。这两个接口将继续被支持。详情见 设置头字段。 - HttpResponse、SimpleTemplateResponse 以及 TemplateResponse 的新
headers
参数允许在实例化时设置响应的 headers。
安全
SECRET_KEY 配置现在是在第一次访问时检查有效值,而不是在第一次加载设置时。这使得运行不依赖
SECRET_KEY
的管理命令不需要提供一个值。因此,在没有提供有效的SECRET_KEY
的情况下调用 configure(),然后继续访问settings.SECRET_KEY
现在会引发一个 ImproperlyConfigured 异常。新的
Signer.sign_object()
和Signer.unsign_object()
方法允许签署复杂数据结构。更多细节见 保护复杂的数据结构。另外, signing.dumps() 和
load()
成为 TimestampSigner.sign_object() 和 unsign_object() 的快捷方式。
序列化
信号
- Signal.send_robust() 现在会记录异常。
模板
- floatformat 模板过滤器现在允许使用
g
后缀来强制按 THOUSAND_SEPARATOR 对活动 locale 进行分组 - 用 缓存的模板加载器 缓存的模板现在可以在开发模式中正确地重新加载。
测试
- 在 TestCase.setUpTestData() 中分配给类属性的对象现在对每个测试方法都是孤立的。这些对象现在需要支持用 copy.deepcopy() 创建深度拷贝。指定不支持
deepcopy()
的对象已被废弃,并将在 Django 4.1 中被移除。 - DiscoverRunner 现在默认启用 faulthandler。这可以通过使用 test —no-faulthandler 选项来禁用。
- DiscoverRunner 和 test 管理命令现在可以跟踪计时,包括数据库设置和总运行时间。这可以通过使用 test —timing 选项来启用。
- Client 现在在跟随 307 和 308 重定向时保留了请求的查询字符串。
- 新的 TestCase.captureOnCommitCallbacks() 方法在一个列表中捕获传递给 transaction.on_commit() 的回调函数。这允许你在不使用较慢的 TransactionTestCase 的情况下测试此类回调。
- TransactionTestCase.assertQuerysetEqual() now supports direct comparison against another queryset rather than being restricted to comparison against a list of string representations of objects when using the default value for the
transform
argument.
实用程序
django.utils.timesince.timesince()
和django.utils.timesince.timeuntil()
函数的新depth
参数允许指定要返回的相邻时间单位的数量。
验证器
- 内置的验证器现在包括提供的值在提出的 ValidationError 的
params
参数。这允许自定义错误信息使用%(value)s
占位符。 - ValidationError 相等运算符现在忽略了
messages
和params
的排序。
3.2 中向后不兼容的更改
数据库后端 API
本节介绍了第三方数据库后端可能需要的更改。
- 新的
DatabaseFeatures.introspected_field_types
属性取代了这些特性:can_introspect_autofield
can_introspect_big_integer_field
can_introspect_binary_field
can_introspect_decimal_field
can_introspect_duration_field
can_introspect_ip_address_field
can_introspect_positive_integer_field
can_introspect_small_integer_field
can_introspect_time_field
introspected_big_auto_field_type
introspected_small_auto_field_type
introspected_boolean_field_type
- 要启用对覆盖索引(Index.include)和覆盖唯一约束(UniqueConstraint.include)的支持,设置
DatabaseFeatures.supports_covering_indexes
为True
。 - 第三方数据库后端必须实现对
CharField
和TextField
的列数据库校对的支持,或者将DatabaseFeatures.supports_collation_on_charfield
和DatabaseFeatures.supports_collation_on_textfield
设为False
。如果不支持非确定的排序,请将supports_non_deterministic_collations
设为False
。 DatabaseOperations.random_function_sql()
已被删除,改用新的Random
数据库函数。DatabaseOperations.date_trunc_sql()
和DatabaseOperations.time_trunc_sql()
现在接受可选的tzname
参数,以便在特定的时区进行截断。DatabaseClient.runshell()
现在可以从DatabaseClient.settings_to_cmd_args_env()
方法中获得参数和带有环境变量的可选字典给底层命令行客户端。第三方数据库后端必须实现DatabaseClient.settings_to_cmd_args_env()
或覆盖DatabaseClient.runshell()
。- 第三方数据库后端必须实现对函数索引的支持(Index.expressions)或者将
DatabaseFeatures.supports_expression_indexes
设为False
。如果COLLATE
不是CREATE INDEX
语句的一部分,请将DatabaseFeatures.collate_as_index_expression
设为True
。
django.contrib.admin
- 管理中的分页链接现在是 1 开头索引,而不是 0 开头索引,即第一页的查询字符串是
?p=1
,而不是?p=0
。 - 新的管理全局回退视图将打破在管理 URL 之后路由并匹配管理 URL 前缀的 URL 模式。你可以调整你的 URL 排序,或者,如果有必要,将 AdminSite.final_catch_all_view 设置为
False
,禁用全局回退视图。更多细节见 Django 3.2 新特性。 - 最小化的 JavaScript 文件不再包括在管理中。如果你需要这些文件被最小化,请考虑使用第三方应用程序或外部构建工具。与管理一起打包的已被最小化的 JavaScript 文件(例如 jquery.min.js)仍然包括在内。
- ModelAdmin.prepopulated_fields 不再剥离英文停顿词,例如
'a'
或'an'
。
django.contrib.gis
- 移除对 PostGIS 2.2 的支持。
- Oracle 后端现在在调整多边形(和包含多边形的几何体集合)的方向并将其保存到数据库之前克隆它们。它们不再是可原地变更的。如果你在模型被保存后使用多边形,你可能会注意到这一点。
丢弃了对 PostgreSQL 9.5 的支持
对 PostgreSQL 9.5 的上游支持在 2021 年 2 月结束。Django 3.2 支持 PostgreSQL 9.6 及以上版本。
丢弃了对 MySQL 5.6 的支持
对 MySQL 5.6 的上游支持在 2021 年 4 月结束。Django 3.2 支持 MySQL 5.7 及以上版本。
杂项
Django 现在支持非
pytz
时区,例如 Python 3.9+ 的 zoneinfo 模块及其向后移植版本。未记录的
SpatiaLiteOperations.proj4_version()
方法改名为proj_version()
。slugify() 现在可以删除前面和后面的破折号以及下划线。
The intcomma and intword template filters no longer depend on the
USE_L10N
setting.移除对
argon2-cffi
< 19.1.0 的支持。当国际化被禁用(
USE_I18N = False
)和本地化被启用(USE_L10N = True
)时,缓存键不再包括语言。在这样的配置下,升级到 Django 3.2 后,对任何以前的缓存值的第一次请求将是一次缓存丢失。ForeignKey.validate()
现在使用 _base_manager 而不是 _default_manager 来检查相关实例是否存在。当一个应用程序在
apps.py
子模块中定义了一个 AppConfig 子类,Django 现在会自动使用这个配置,即使它没有用default_app_config
启用。如果你需要防止这种行为,请在 AppConfig 子类中设置default = False
。更多细节见 Django 3.2 新特性。实例化一个抽象模型现在会引发
TypeError
。对 setup_databases() 的关键字参数现在是只能用关键字。
删除了无文档的
django.utils.http.limited_parse_qsl()
函数。请使用 urllib.parse.parse_qsl() 代替。django.test.utils.TestContextDecorator
现在使用 addCleanup() 所以在 setUp() 方法中注册的清理会在TestContextDecorator.disable()
前被调用。当一个会话在并发请求中被销毁时,
SessionMiddleware
现在会引发SessionInterrupted
异常,而不是 SuspiciousOperation。django.db.models.Field 相等运算符现在可以正确区分跨模型的继承字段实例。此外,此类字段的排序现在也被定义了。
未记录的
django.core.files.locks.lock()
函数现在在文件不能被锁定时返回False
,而不是引发 BlockingIOError。密码重置机制现在在用户电子邮件改变时使令牌无效。
makemessages 命令不再处理使用 makemessages —locale 选项指定的无效 locale,如果它们包含连字符(
'-'
)。django.contrib.auth.forms.ReadOnlyPasswordHashField
表单字段现在默认为 disabled。因此UserChangeForm.clean_password()
不再需要返回初始值。cache.get_many()
、get_or_set()
、has_key()
、incr()
、decr()
、incr_version()
和decr_version()
的缓存操作现在可以正确处理缓存中的None
,与其他值相同,而不是表现为键不存在。由于
python-memcached
的限制,以前的行为被保留在已废弃的MemcachedCache
后端。SQLite 的最小支持版本从 3.8.3 增加到 3.9.0。
CookieStorage 现在以 RFC 6265 兼容的格式存储信息。对使用旧格式的 cookie 的支持仍然保留到 Django 4.1。
asgiref
的最小支持版本从 3.2.10 提高到 3.3.2。
在 3.2 中被废弃的功能
杂项
- 在 TestCase.setUpTestData() 中,将不支持用 copy.deepcopy() 创建深度拷贝的对象分配给类属性的做法已被废弃。
- 在 BaseCommand.requires_system_checks 中使用一个布尔值已被废弃。使用
'__all__'
来代替True
,使用[]
(一个空列表)来代替False
。 - EmailValidator 的
whitelist
参数和domain_whitelist
属性已被废弃。使用allowlist
代替whitelist
,domain_allowlist
代替domain_whitelist
。你可能需要在现有的迁移中重命名whitelist
。 default_app_config
应用程序配置变量已被废弃,因为现在自动发现了AppConfig
。更多细节请参见 Django 3.2 新特性。- 在
TransactionTestCase.assertQuerysetEqual()
中与字符串值比较时自动调用repr()
,已被废弃。如果你需要以前的行为,明确设置transform
为repr
。 django.core.cache.backends.memcached.MemcachedCache
后端已被废弃,因为python-memcached
有一些问题,而且似乎无人维护。使用django.core.cache.backends.memcached.PyMemcacheCache
或django.core.cache.backends.memcached.PyLibMCCache
代替。django.contrib.messages.storage.cookie.CookieStorage
使用的消息格式与旧版本的 Django 生成的格式不同。对旧格式的支持一直持续到 Django 4.1。