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 支持¶
新的 django.core.cache.backends.memcached.PyMemcacheCache 缓存后端允许使用 pymemcache 库来操作 memcached。要求使用 pymemcache 的版本必须是 3.4.0 或更高。有关更多详细信息,请参阅 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¶
DataSource类现在支持pathlib.Path。LayerMapping类现在支持pathlib.Path。
django.contrib.postgres¶
新的
ExclusionConstraint.include属性允许在 PostgreSQL 12+ 上创建覆盖排除约束。新的
ExclusionConstraint.opclasses属性允许设置 PostgreSQL 操作符类。The new
JSONBAgg.orderingattribute determines the ordering of the aggregated elements.新的
JSONBAgg.distinct属性决定了聚合的值是否会是唯一的。CreateExtension操作现在会检查数据库中是否已经存在扩展,如果存在则跳过迁移过程。新的
CreateCollation和RemoveCollation操作允许在 PostgreSQL 上创建和删除排序。参见 使用迁移来管理整理 获取更多细节。对
ArrayField的查找现在允许包含表达式的(非嵌套)数组作为右侧。
django.contrib.sitemaps¶
新的
Sitemap属性alternates、languages和x_default允许生成网站地图 替换为 你页面的本地化版本。
数据库后端¶
第三方数据库后端现在可以使用新的
DatabaseFeatures.django_test_skips和django_test_expected_failures属性在 Django 测试套件中跳过或标记为预期失败的测试。
装饰器¶
新的
no_append_slash()装饰器允许个别视图从APPEND_SLASHURL 规范化中排除。
错误报告¶
自定义
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参数允许截断特定时区的数据时间。添加了
Random数据库函数。聚合函数、
F()、OuterRef()以及其他表达式现在允许使用变换。详情参见 表达式可以引用变换。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()现在支持直接与另一个查询集进行比较,而不仅仅是在使用默认值的情况下与对象的字符串表示列表进行比较时。
实用程序¶
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_autofieldcan_introspect_big_integer_fieldcan_introspect_binary_fieldcan_introspect_decimal_fieldcan_introspect_duration_fieldcan_introspect_ip_address_fieldcan_introspect_positive_integer_fieldcan_introspect_small_integer_fieldcan_introspect_time_fieldintrospected_big_auto_field_typeintrospected_small_auto_field_typeintrospected_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()现在可以删除前面和后面的破折号以及下划线。移除对
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。