# Django 3.2.11.dev 文档

# 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` 数据时可以实例化的最大表单数量。更多细节请参见 Limiting the maximum number of instantiated forms。
- `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 操作符类。
- 新的 `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` 数据时可实例化的最大表单数量。参见 Limiting the maximum number of instantiated forms 以了解更多细节。
- `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()` 的快捷方式。

#### 序列化

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

#### 信号

- `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()` 现在支持与另一个查询集进行直接比较，而不是在使用 `transform` 参数的默认值时被限制为与对象的字符串表示列表进行比较。

#### 实用程序

- `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` 现在使用 `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。