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')。它的引入是为了向后兼容前者的风格,目的是将生态系统切换到后者,但这种切换并没有发生。

随着自动发现 AppConfigdefault_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_FIELDAutoField

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_displayreadonly_fields 一起使用。

同样,新的 action() 装饰器允许轻松地将选项添加到可与 actions 一起使用的动作函数。

使用 @display 装饰器的好处是,现在可以在需要指定自定义方法的属性时使用 @property 装饰器。在此之前,有必要在为方法指定所需的属性后使用 property() 函数来代替。

使用装饰器的好处是这些选项更容易被发现,因为它们可以被代码编辑器中的补全工具所提示。它们仅仅是一种方便,并且仍然在幕后的函数上设置相同的属性。

次要特性

django.contrib.admin

  • ModelAdmin.search_fields 现在允许针对带空格的引号短语进行搜索。

  • 如果在管理中注册了目标模型,只读的相关字段现在被呈现为可浏览的链接。

  • 管理现在支持主题化,包括一个根据浏览器配置启用的暗色主题。更多细节见 主题化支持

  • ModelAdmin.autocomplete_fields 现在搜索一个相关模型时尊重 ForeignKey.to_fieldForeignKey.limit_choices_to

  • 管理现在安装了一个全局最终回退视图,将未经认证的用户重定向到登录页面,无论该 URL 是否有效。这可以防止潜在的模型枚举隐私问题。

    尽管不推荐,你可以将新的 AdminSite.final_catch_all_view 设置为 False 来禁用所有视图。

django.contrib.auth

  • PBKDF2 密码散列器的默认迭代次数从 216,000 次增加到 260,000 次。

  • Argon2 密码散列器的默认变量改为 Argon2id。memory_costparallelism 分别增加到 102,400 和 8,以符合 argon2-cffi 的默认值。

    增加 memory_cost 将所需的内存从 512KB 推到 100MB。这仍然是相当保守的,但在内存有限的环境中可能会导致问题。如果是这种情况,可以对现有的散列器进行子类化以覆盖默认值。

  • Argon2, MD5, PBKDF2, SHA-1 密码散列器的默认盐熵从 71 位增加到 128 位。

django.contrib.contenttypes

django.contrib.postgres

  • 新的 ExclusionConstraint.include 属性允许在 PostgreSQL 12+ 上创建覆盖排除约束。
  • The new ExclusionConstraint.opclasses attribute allows setting PostgreSQL operator classes.
  • 新的 JSONBAgg.ordering 属性决定了聚合元素的排序。
  • 新的 JSONBAgg.distinct 属性决定了聚合的值是否会是唯一的。
  • CreateExtension 操作现在会检查数据库中是否已经存在扩展,如果存在则跳过迁移过程。
  • 新的 CreateCollationRemoveCollation 操作允许在 PostgreSQL 上创建和删除排序。参见 使用迁移来管理整理 获取更多细节。
  • ArrayField 的查找现在允许包含表达式的(非嵌套)数组作为右侧。
  • 新的 OpClass() 表达式允许在具有自定义运算符类的表达式上创建函数索引。参见 函数索引 获取更多细节。

django.contrib.sitemaps

django.contrib.syndication

  • 新的 item_comments 钩子允许为每个 feed 项目指定一个评论 URL。

数据库后端

  • 第三方数据库后端现在可以使用新的 DatabaseFeatures.django_test_skipsdjango_test_expected_failures 属性在 Django 测试套件中跳过或标记为预期失败的测试。

装饰器

错误报告

  • 自定义 ExceptionReporter 子类现在可以定义 html_template_pathtext_template_path 属性来重写用于渲染异常报告的模板。

文件上传

表单

通用视图

管理命令

  • loaddata 现在支持存储在 XZ 档案(.xz)和 LZMA 档案(.lzma)中的固定数据。
  • dumpdata 现在可以压缩 bz2gzlzmaxz 格式的数据。
  • makemigrations 现在可以在没有数据库连接的情况下调用。在这种情况下,会跳过检查是否有一致的迁移历史。
  • BaseCommand.required_system_checks 现在支持指定一个标签列表。在所选标签中注册的系统检查将在执行命令前被检查出错误。在之前的版本中,所有的系统检查或者都不执行,或者都会被执行。
  • 更新了对 Windows 上彩色终端输出的支持。各种现代终端环境被自动检测到,在其他情况下启用支持的选项也被改进。更多细节见 语法着色

迁移

  • 新的 Operation.migration_name_fragment 属性允许提供一个文件名片段,该片段将被用来命名只包含该操作的迁移。
  • 迁移现在支持从 pathlibos.PathLike 实例中序列化纯路径和具体路径对象。

模型

  • 在 PostgreSQL 上支持 QuerySet.select_for_update() 的新的 no_key 参数,允许获得较弱的锁,不会阻止创建通过外键引用被锁定行的新行。
  • When() 表达式现在允许使用 condition 参数与 lookups
  • 新的 Index.includeUniqueConstraint.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 子类,适用于 boolbytesfloatintstrdatetime.datedatetime.datetimedatetime.timedatetime.timedeltadecimal.Decimaluuid.UUID 实例。因此,在使用 Value() 时,解析数据库函数和组合表达式的 output_field 现在可能会因混合类型而崩溃。在这种情况下,你将需要明确地设置 output_field
  • 新的 QuerySet.alias() 方法允许为表达式创建可重复使用的别名,这些表达式不需要被选择,但可用于过滤、排序,或作为复杂表达式的一部分。
  • 新的 Collate 函数允许通过指定的数据库排列方式进行过滤和排序。
  • 如果在 QuerySet.distinct() 中只指定了一个字段,QuerySet.in_bulk()field_name 参数现在可以接受不同的字段。
  • TruncDateTruncTime 数据库函数的新 tzinfo 参数允许截断特定时区的数据时间。
  • CharFieldTextField 新增的 db_collation 参数允许为字段设置一个数据库排序。
  • 添加了 Random 数据库函数。
  • 聚合函数F()OuterRef() 以及其他表达式现在允许使用变换。详情参见 Expressions can reference transforms
  • atomic() 的新参数 durable 保证在原子块中所做的更改将被提交,如果该块退出时没有错误。嵌套的原子块被标记为耐用,将引发一个 RuntimeError
  • 添加了 JSONObject 数据库函数。

分页

请求和响应

安全

序列化

  • 新的 JSONL 序列化器允许使用 JSON Lines 格式与 dumpdataloaddata。这对填充大型数据库很有用,因为数据是逐行加载到内存中的,而不是一次性加载。

信号

模板

测试

实用程序

  • django.utils.timesince.timesince()django.utils.timesince.timeuntil() 函数的新 depth 参数允许指定要返回的相邻时间单位的数量。

验证器

  • 内置的验证器现在包括提供的值在提出的 ValidationErrorparams 参数。这允许自定义错误信息使用 %(value)s 占位符。
  • ValidationError 相等运算符现在忽略了 messagesparams 的排序。

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_indexesTrue
  • 第三方数据库后端必须实现对 CharFieldTextField 的列数据库校对的支持,或者将 DatabaseFeatures.supports_collation_on_charfieldDatabaseFeatures.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
  • EmailValidatorwhitelist 参数和 domain_whitelist 属性已被废弃。使用 allowlist 代替 whitelistdomain_allowlist 代替 domain_whitelist。你可能需要在现有的迁移中重命名 whitelist
  • default_app_config 应用程序配置变量已被废弃,因为现在自动发现了 AppConfig。更多细节请参见 Django 3.2 新特性
  • TransactionTestCase.assertQuerysetEqual() 中与字符串值比较时自动调用 repr(),已被废弃。如果你需要以前的行为,明确设置 transformrepr
  • django.core.cache.backends.memcached.MemcachedCache 后端已被废弃,因为 python-memcached 有一些问题,而且似乎无人维护。使用 django.core.cache.backends.memcached.PyMemcacheCachedjango.core.cache.backends.memcached.PyLibMCCache 代替。
  • django.contrib.messages.storage.cookie.CookieStorage 使用的消息格式与旧版本的 Django 生成的格式不同。对旧格式的支持一直持续到 Django 4.1。