# Django 6.0.7 documentation

# 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`

- `GDALRaster.transform()` 方法现在支持 `SpatialReference`。

- `DataSource` 类现在支持 `pathlib.Path`。

- `LayerMapping` 类现在支持 `pathlib.Path`。

#### `django.contrib.postgres`

- 新的 `ExclusionConstraint.include` 属性允许在 PostgreSQL 12+ 上创建覆盖排除约束。

- 新的 `ExclusionConstraint.opclasses` 属性允许设置 PostgreSQL 操作符类。

- The new `JSONBAgg.ordering` attribute determines the ordering of the aggregated elements.

- 新的 `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` 实例中序列化纯路径和具体路径对象。

#### 模型

- The new `no_key` parameter for `QuerySet.select_for_update()`, supported on PostgreSQL, allows acquiring weaker locks that don't block the creation of rows that reference locked rows through a foreign key.

- `When()` 表达式现在允许使用 `condition` 参数与 `lookups`。

- 新的 `Index.include` 和 `UniqueConstraint.include` 属性允许在 PostgreSQL 11+ 上创建覆盖索引和覆盖唯一约束。

- 新的 `UniqueConstraint.opclasses` 属性允许设置 PostgreSQL 操作符类。

- `QuerySet.update()` 方法现在尊重 MySQL 和 MariaDB 的 `order_by()` 子句。

- `FilteredRelation()` 现在支持嵌套关系。

- The `of` argument of `QuerySet.select_for_update()` is now allowed on MySQL 8.0.1+.

- `Value()` expression now automatically resolves its `output_field` to the appropriate `Field` subclass based on the type of its provided `value` for `bool`, `bytes`, `float`, `int`, `str`, `datetime.date`, `datetime.datetime`, `datetime.time`, `datetime.timedelta`, `decimal.Decimal`, and `uuid.UUID` instances. As a consequence, resolving an `output_field` for database functions and combined expressions may now crash with mixed types when using `Value()`. You will need to explicitly set the `output_field` in such cases.

- 新的 `QuerySet.alias()` 方法允许为表达式创建可重复使用的别名，这些表达式不需要被选择，但可用于过滤、排序，或作为复杂表达式的一部分。

- 新的 `Collate` 函数允许通过指定的数据库排列方式进行过滤和排序。

- The `field_name` argument of `QuerySet.in_bulk()` now accepts distinct fields if there's only one field specified in `QuerySet.distinct()`.

- `TruncDate` 和 `TruncTime` 数据库函数的新 `tzinfo` 参数允许截断特定时区的数据时间。

- 为 `CharField` 和 `TextField` 新增的 `db_collation` 参数允许为字段设置一个数据库排序。

- 添加了 `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()` 的快捷方式。

#### 序列化

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

#### 信号

- `Signal.send_robust()` 现在会记录异常。

#### 模板

- `floatformat` 模板过滤器现在允许使用 `g` 后缀来强制按 `THOUSAND_SEPARATOR` 对活动 locale 进行分组

- 用 缓存的模板加载器 缓存的模板现在可以在开发模式中正确地重新加载。

#### 测试

- Objects assigned to class attributes in `TestCase.setUpTestData()` are now isolated for each test method. Such objects are now required to support creating deep copies with `copy.deepcopy()`. Assigning objects which don't support `deepcopy()` is deprecated and will be removed in Django 4.1.

- `DiscoverRunner` now enables `faulthandler` by default. This can be disabled by using the `test --no-faulthandler` option.

- `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_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()` 现在可以删除前面和后面的破折号以及下划线。

- `intcomma` 和 `intword` 模板过滤器不再依赖于 `USE_L10N` 设置。

- 移除对 `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` now uses `addCleanup()` so that cleanups registered in the `setUp()` method are called before `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 中被废弃的功能

### 杂项

- Assigning objects which don't support creating deep copies with `copy.deepcopy()` to class attributes in `TestCase.setUpTestData()` is deprecated.

- 在 `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。