# Django 5.2.8 documentation

# Django 2.2 版本发行说明

2019 年 4 月 1 日

欢迎使用 Django 2.2 ！

这些发布说明涵盖了 新功能，以及在从 Django 2.1 或更早版本升级时需要注意的一些 向后不兼容的更改。我们已经 开始了一些功能的弃用过程。

如果你要更新现有的项目，请看 如何将 Django 更新至新的版本 指南。

Django 2.2 被指定为 长期支持版本。它将在发布后至少三年内接收安全更新。对于之前的 LTS 版本 Django 1.11，支持将在 2020 年 4 月结束。

## Python 兼容性

Django 2.2 支持 Python 3.5、3.6、3.7、3.8（从 2.2.8 版开始），以及 3.9（从 2.2.17 版开始）。我们 强烈建议 并只官方支持每个系列的最新版本。

## Django 2.2 的新功能有哪些呢？

### 约束

新的 `CheckConstraint` 和 `UniqueConstraint` 类允许添加自定义数据库约束。约束可以使用 `Meta.constraints` 选项添加到模型中。

### 次要特性

#### `django.contrib.admin`

- 为 `TabularInline` 的列标题添加了一个 CSS 类。

#### `django.contrib.auth`

- 如果接受，现在将 `HttpRequest` 作为 `RemoteUserBackend.configure_user()` 的第一个位置参数传递。

#### `django.contrib.gis`

- 为 `Envelope` 函数添加了对 Oracle 数据库的支持。

- 为 `coveredby` 和 `covers` 查询添加了对 SpatiaLite 的支持。

#### `django.contrib.postgres`

- 对于 `ArrayAgg` 和 `StringAgg`，新的 `ordering` 参数确定了聚合元素的排序方式。

- 新的 `BTreeIndex`、`HashIndex` 和 `SpGistIndex` 类允许在数据库中创建 `B-Tree`、`hash` 和 `SP-GiST` 索引。

- `BrinIndex` 现在具有 `autosummarize` 参数。

- `SearchQuery` 的新参数 `search_type` 允许搜索短语或原始表达式。

#### `django.contrib.staticfiles`

- 在 `collectstatic --ignore` 选项中添加了路径匹配功能，以便可以使用像 `/vendor/*.js` 这样的模式。

#### 数据库后端

- 在 SQLite 上为 `QuerySet.iterator()` 添加了结果流式传输功能。

#### 通用视图

- 新的 `View.setup` 钩子在调用 `dispatch()` 之前初始化视图属性。它允许 mixins 设置实例属性，以便在子类中重用。

#### 国际化

- 增加了对亚美尼亚语的支持和翻译。

#### 管理命令

- 新的 `--force-color` 选项强制对命令输出进行着色。

- `inspectdb` 现在会为 PostgreSQL 上的外部表创建模型。

- `inspectdb --include-views` 现在会为 Oracle 和 PostgreSQL 上的物化视图创建模型。

- 新的 `inspectdb --include-partitions` 选项允许在 PostgreSQL 上为分区表创建模型。在旧版本中，模型是在子表而不是父表中创建的。

- `inspectdb` 现在可以为 Oracle 和 PostgreSQL 自动检测 `DurationField`，以及为 SQLite 检测 `AutoField`。

- 在 Oracle 上，如果可用，`dbshell` 会使用 `rlwrap` 包装。`rlwrap` 提供了命令历史记录和键盘输入的编辑功能。

- 新的 `makemigrations --no-header` 选项可以避免在生成的迁移文件中写入头部注释。这个选项也适用于 `squashmigrations`。

- `runserver` 现在可以使用 Watchman 来提高监视大量文件变化的性能。

#### 迁移

- 新的 `migrate --plan` 选项会打印将执行的迁移操作列表。

- `NoneType` 现在可以在迁移中序列化。

- 现在可以为迁移 注册自定义序列化程序。

#### 模型

- 添加了对 PostgreSQL 运算符类 (`Index.opclasses`) 的支持。

- 添加了对部分索引 (`Index.condition`) 的支持。

- 添加了 `NullIf` 和 `Reverse` 数据库函数，以及许多 数学数据库函数。

- 将 `QuerySet.bulk_create()` 的新参数 `ignore_conflicts` 设置为 `True` 会告诉数据库忽略插入失败的行，即违反唯一性约束或其他检查的行。

- 新的 `ExtractIsoYear` 函数从 `DateField` 和 `DateTimeField` 中提取 ISO-8601 周编号年，新的 `iso_year` 查询允许按 ISO-8601 周编号年进行查询。

- 新的 `QuerySet.bulk_update()` 方法允许高效地更新多个模型实例上的特定字段。

- Django 不再总是在执行单个查询时启动事务，例如 `Model.save()`, `QuerySet.update()` 和 `Model.delete()`。这通过减少数据库往返次数来提高自动提交的性能。

- 为 `StdDev` 和 `Variance` 函数添加了 SQLite 支持。

- 对于 `Aggregate` 类，增加了 `DISTINCT` 聚合的处理。在 `Aggregate` 子类上添加 `allow_distinct = True` 作为类属性，允许在初始化时指定一个 `distinct` 关键字参数，以确保聚合函数仅对 `expressions` 的每个不同值调用一次。

- 现在允许在具有中间模型的多对多关系上使用 `RelatedManager.add()`、`create()`、`remove()`、`set()`、`get_or_create()` 和 `update_or_create()` 方法。新的 `through_defaults` 参数用于指定新中间模型实例的值。

#### 请求和响应

- 添加了 `HttpRequest.headers`，以便简单访问请求的头部信息。

#### 序列化

- 现在可以通过将 `handle_forward_references=True` 传递给 `serializers.deserialize()` 来使用包含 前向引用 的自然键反序列化数据。此外，`loaddata` 现在会自动处理前向引用。

#### 测试

- 新的 `SimpleTestCase.assertURLEqual()` 断言检查给定的 URL，忽略查询字符串的顺序。`assertRedirects()` 使用了这个新的断言。

- 现在，测试 `Client` 在 `content_type='application/json'` 时支持自动对列表和元组 `data` 进行 JSON 序列化。

- 新的 `ORACLE_MANAGED_FILES` 测试数据库设置允许使用 Oracle 管理文件 (OMF) 表空间。

- 可延迟的数据库约束现在在 SQLite 3.20+ 上的每个 `TestCase` 测试结束时进行检查，就像其他支持可延迟约束的后端一样。对于较旧版本的 SQLite，这些检查没有实现，因为在那里需要昂贵的表内省。

- `DiscoverRunner` 现在会跳过未被 测试引用 的数据库的设置。

#### URLs

- 新的 `ResolverMatch.route` 属性存储匹配的 URL 模式的路由。

#### 验证器

- `MaxValueValidator`、`MinValueValidator`、`MinLengthValidator` 和 `MaxLengthValidator` 现在接受可调用的 `limit_value`。

## 2.2 版本中的不向后兼容变更

### 数据库后端 API

本节介绍了第三方数据库后端可能需要的更改。

- 第三方数据库后端必须实现对表检查约束的支持，或将 `DatabaseFeatures.supports_table_check_constraints` 设置为 `False`。

- 第三方数据库后端必须实现在插入时忽略约束或唯一性错误的支持，或将 `DatabaseFeatures.supports_ignore_conflicts` 设置为 `False`。

- 第三方数据库后端必须实现对 `DurationField` 的内省，或将 `DatabaseFeatures.can_introspect_duration_field` 设置为 `False`。

- `DatabaseFeatures.uses_savepoints` 现在默认为 `True`。

- 第三方数据库后端必须实现对部分索引的支持，或将 `DatabaseFeatures.supports_partial_indexes` 设置为 `False`。

- 移除了 `DatabaseIntrospection.table_name_converter()` 和 `column_name_converter()`。第三方数据库后端可能需要代替实现 `DatabaseIntrospection.identifier_converter()`。在这种情况下，`DatabaseIntrospection.get_constraints()` 返回的约束名称必须通过 `identifier_converter()` 进行规范化。

- 索引的 SQL 生成从 `Index` 移动到 `SchemaEditor`，并添加了以下 `SchemaEditor` 方法：

  - `_create_primary_key_sql()` 和 `_delete_primary_key_sql()`

  - `_delete_index_sql()` （与 `_create_index_sql()` 配对使用）

  - `_delete_unique_sql` （与 `_create_unique_sql()` 配对使用）

  - `_delete_fk_sql()` （与 `_create_fk_sql()` 配对使用）

  - `_create_check_sql()` 和 `_delete_check_sql()`

- 移除了 `DatabaseWrapper.__init__()` 的第三个参数 `allow_thread_sharing`。

### 不再从基本的 `ModelAdmin` 类中收集管理操作

例如，在较旧版本的 Django 中：

    from django.contrib import admin

    class BaseAdmin(admin.ModelAdmin):
        actions = ["a"]

    class SubAdmin(BaseAdmin):
        actions = ["b"]

`SubAdmin` 将具有操作 `'a'` 和 `'b'`。

现在，`actions` 遵循标准的 Python 继承。要获得与以前相同的结果：

    class SubAdmin(BaseAdmin):
        actions = BaseAdmin.actions + ["b"]

### `django.contrib.gis`

- 支持 GDAL 1.9 和 1.10 的功能已被移除。

### `TransactionTestCase` 序列化数据加载

现在，在 `TransactionTestCase` 的测试结束后，即在数据库刷新之后加载初始数据迁移。在旧版本中，这些数据在测试开始时加载，但这会阻止 `test --keepdb` 选项正常工作（整个测试套件结束后数据库为空）。除非您已自定义了 `TransactionTestCase` 的内部，否则这个变化不应影响您的测试。

### `sqlparse` 是必需的依赖项

为了简化 Django 数据库处理的几个部分，现在 sqlparse 0.2.2+ 是一个必需的依赖项。它会随着 Django 自动安装。

### `cached_property` 别名

在以下用法中：

    from django.utils.functional import cached_property

    class A:
        @cached_property
        def base(self):
            return ...

        alias = base

`alias` 不会被缓存。在可以检测到问题的情况下（Python 3.6 及更高版本），此类用法现在会引发 `TypeError: Cannot assign the same cached_property to two different names ('base' and 'alias')`。

请改用以下方式：

    import operator

    class A:
        ...

        alias = property(operator.attrgetter("base"))

### 代理模型的权限

代理模型的权限 现在使用代理模型的内容类型而不是具体模型的内容类型来创建。在运行 `migrate` 时，迁移将更新现有的权限。

在管理界面中，对于与其具体模型具有相同的 `app_label` 的代理模型，这个变化是透明的。然而，在旧版本中，对于具体模型具有不同 `app_label` 的代理模型的权限的用户不能访问管理中的模型。现在这个问题已经修复，但在升级之前，您可能希望审查这些代理模型的权限分配（`[add|view|change|delete]_myproxy`），以确保新的访问是合适的。

最后，代理模型的权限字符串必须更新以使用它们自己的 `app_label`。例如，对于继承自 `other_app.ConcreteModel` 的 `app.MyProxyModel`，请将 `user.has_perm('other_app.add_myproxymodel')` 更新为 `user.has_perm('app.add_myproxymodel')`。

### 合并表单 `Media` 资源

现在，表单 `Media` 资源使用拓扑排序算法进行合并，因为旧的成对合并算法对某些情况不足够。不包含其依赖项的 CSS 和 JavaScript 文件现在可能会被错误地排序（而旧算法恰好由于巧合而产生了正确的结果）。

请审查所有的 `Media` 类以查找任何缺失的依赖项。例如，依赖于 `django.jQuery` 的小部件在 声明表单媒体资源 时必须指定 `js=['admin/js/jquery.init.js', ...]`。

### 杂项

- 为了提高可读性，`UUIDField` 表单字段现在会显示带有破折号的值，例如 `550e8400-e29b-41d4-a716-446655440000`，而不是 `550e8400e29b41d4a716446655440000`。

- 在 SQLite 上，`PositiveIntegerField` 和 `PositiveSmallIntegerField` 现在包含一个检查约束，以防止在数据库中出现负值。如果您有现有的无效数据并运行重新创建表的迁移，您将看到 `CHECK constraint failed`。

- 为了与 WSGI 服务器保持一致，测试客户端现在将 `Content-Length` 头设置为字符串而不是整数。

- `django.utils.text.slugify()` 的返回值不再标记为 HTML 安全。

- `urlizetrunc`、`truncatechars`、`truncatechars_html`、`truncatewords` 和 `truncatewords_html` 模板过滤器使用的默认截断字符现在是真正的省略号字符（`…`）而不是 3 个点。您可能需要调整一些测试输出的比较。

- 不再支持在模板文件系统加载器中使用字节串路径。

- `django.utils.http.urlsafe_base64_encode()` 现在返回一个字符串而不是字节字符串，并且 `django.utils.http.urlsafe_base64_decode()` 可能不再接受字节字符串作为参数。

- 不再支持 `cx_Oracle` 版本低于 6.0。

- `mysqlclient` 的最低支持版本从 1.3.7 增加到 1.3.13。

- SQLite 的最低支持版本从 3.7.15 提高到 3.8.3 。

- 为了提供更语义化的查询数据，`NullBooleanSelect` 现在呈现 `<option>` 的值为 `unknown`、`true` 和 `false`，而不是 `1`、`2` 和 `3`。为了向后兼容，旧值仍然被接受为数据。

- `Group.name` 的 `max_length` 从 80 增加到 150 个字符。

- 现在在运行于 SQLite 3.20+ 上的测试中，违反可延迟数据库约束的行为将报错，就像其他支持此类约束的后端一样。

- 为了捕获使用错误，测试 `Client` 和 `django.utils.http.urlencode()` 现在如果传递 `None` 作为要编码的值会引发 `TypeError`，因为 `None` 不能编码为 GET 和 POST 数据。要么传递空字符串，要么省略值。

- 现在，`ping_google` 管理命令默认使用 `https` 而不是 `http` 作为站点地图的 URL。如果你的站点使用 http，请使用新的 `ping_google --sitemap-uses-http` 选项。如果你使用 `django.contrib.sitemaps.ping_google` 函数，请将新的 `sitemap_uses_https` 参数设置为 `False`。

- `runserver` 不再支持 `pyinotify` （已被 Watchman 替代）。

- 当输入是 `Decimal` 时， `Avg`、`StdDev` 和 `Variance` 聚合函数现在返回 `Decimal` 而不是 `float`。

- 如果没有迁移的应用与具有迁移的应用有关系，那么在 SQLite 上的测试将失败。这自从 Django 1.7 添加迁移以来一直是一个已记录的限制，但现在它失败得更可靠。您将看到类似于 `no such table: <app_label>_<model>` 的错误导致测试失败。这在一些具有测试中没有迁移的模型的第三方应用中观察到。您必须为这些模型添加迁移。

- 在 `cache.delete()` 或 `cache.get()` 的 `key` 参数中提供整数现在会引发 `ValueError`。

- 由于已纳入 Transifex 的最新版本，某些语言的复数规则方程式已被更改。

  Note

  在 Django 2.2.12 中添加了处理同一语言的 `.po` 文件中包含不同复数方程的能力。

## 在 2.2 中被废弃的功能

### 模型的 `Meta.ordering` 将不再影响 `GROUP BY` 查询。

模型的 `Meta.ordering` 影响 `GROUP BY` 查询（例如 `.annotate().values()`）是常见的引发混淆的原因。现在，这种查询会发出一个弃用警告，建议添加一个 `order_by()` 以保留当前查询。从 Django 3.1 开始，在这种查询中将忽略 `Meta.ordering`。

### 杂项

- `django.utils.timezone.FixedOffset` 已被弃用，建议使用 `datetime.timezone`。

- 未记录的 `QuerySetPaginator` 别名 `django.core.paginator.Paginator` 已被弃用。

- `django.contrib.postgres` 中的 `FloatRangeField` 模型和表单字段已被弃用，推荐使用新名称 `DecimalRangeField`，以匹配数据库中使用的 `numrange` 数据类型。

- `FILE_CHARSET` 设置已被弃用。从 Django 3.1 开始，从磁盘读取的文件必须是 UTF-8 编码的。

- `django.contrib.staticfiles.storage.CachedStaticFilesStorage` 已被弃用，因为它存在无法解决的问题。请改用 `ManifestStaticFilesStorage` 或第三方云存储。

- 现在，`RemoteUserBackend.configure_user()` 方法的第一个位置参数是 `request`，如果该方法接受它的话。不支持不接受 `request` 参数的覆盖方法，将在 Django 3.1 中移除。

- `SimpleTestCase.allow_database_queries`、`TransactionTestCase.multi_db` 和 `TestCase.multi_db` 属性已被弃用，推荐使用 `SimpleTestCase.databases`、`TransactionTestCase.databases` 和 `TestCase.databases`。这些新属性允许声明数据库依赖关系，以防止非默认数据库的意外查询在测试之间泄漏状态。以前的行为可以通过设置 `databases='__all__'` 来实现，即 `allow_database_queries=True` 和 `multi_db=True`。