# Django 5.2.8 documentation

# Django 3.0 版本发行说明

2019 年 12 月 2 日

欢迎使用 Django 3.0 ！

这些发行说明涵盖了 新功能，以及一些 不兼容的变化，当您从 Django 2.2 或更早版本升级时需要注意。我们已经 删除了一些已经完成了其弃用周期的功能，并且我们已经 开始了一些功能的弃用过程。

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

## Python 兼容性

Django 3.0 支持 Python 3.6、3.7、3.8 和 3.9（截至 3.0.11 版）。我们 强烈推荐 并且只官方支持每个系列的最新版本。

Django 2.2.x 系列是最后一个支持 Python 3.5 的版本。

## 对于较旧版本的 Django 的第三方库支持

在发布 Django 3.0 后，我们建议第三方应用程序作者停止支持 Django 2.2 之前的所有版本。在那个时候，您应该能够使用 `python -Wd` 运行您包的测试，以便看到弃用警告。在进行弃用警告修复后，您的应用程序应该与 Django 3.0 兼容。

## Django 3.0 新特性

### MariaDB 支持

Django 现在正式支持 MariaDB 10.1 及更高版本。更多详情请参阅 MariaDB 注意事项。

### ASGI 支持

Django 3.0 开始了我们使 Django 完全支持异步的旅程，通过提供作为 ASGI 应用程序运行的支持。

这是在我们现有的 WSGI 支持之外的补充。 Django 计划在可预见的未来同时支持两者。然而，异步功能只适用于在 ASGI 下运行的应用程序。

在当前阶段，异步支持仅适用于外部 ASGI 应用程序。内部的所有内容仍然是同步的。异步中间件、视图等尚不受支持。但是，您可以在 Django 应用程序周围使用 ASGI 中间件，从而可以将 Django 与其他 ASGI 框架结合使用。

除非您想开始尝试异步代码，否则没有必要切换您的应用程序，但如果您想了解更多信息，我们有关于使用 ASGI 部署的 文档。

请注意，由于这个改变的副作用，Django 现在可以识别异步事件循环，并会阻止您从异步上下文中调用标记为 "async unsafe" 的代码，比如 ORM 操作。如果您以前从异步代码中使用 Django，那么如果使用不正确，这可能会触发问题。如果看到 `SynchronousOnlyOperation` 错误，请仔细检查您的代码，并将任何数据库操作移动到同步的子线程中。

### PostgreSQL 上的排除约束

新的 `ExclusionConstraint` 类允许在 PostgreSQL 上添加排除约束。约束通过在模型中使用 `Meta.constraints` 选项来添加。

### 过滤表达式

现在可以直接在 `QuerySet` 过滤器中使用输出 `BooleanField` 的表达式，而不需要首先注释然后对注释进行过滤。

### 模型字段选择的枚举类型

现在可以使用自定义枚举类型 `TextChoices`、`IntegerChoices` 和 `Choices` 来定义 `Field.choices`。`TextChoices` 和 `IntegerChoices` 类型用于文本和整数字段。`Choices` 类允许为其他具体数据类型定义兼容的枚举。这些自定义枚举类型支持可翻译的人类可读标签，并可以通过枚举或其成员的属性来访问。有关更多详细信息和示例，请参阅 枚举类型。

### 次要特性

#### `django.contrib.admin`

- 在 `ModelAdmin.list_display` 中的属性上添加了对 `admin_order_field` 属性的支持。

- 新的 `ModelAdmin.get_inlines()` 方法允许根据请求或模型实例来指定内联。

- Select2 库的版本已从 4.0.3 升级到 4.0.7 。

- jQuery 的版本已从 3.3.1 升级到 3.4.1 。

#### `django.contrib.auth`

- 在 `PasswordResetConfirmView` 中新增了 `reset_url_token` 属性，允许指定作为密码重置 URL 组件显示的令牌参数。

- 添加了 `BaseBackend` 类，以便更容易自定义身份验证后端。

- Added `get_user_permissions()` method to mirror the existing `get_group_permissions()` method.

- 在 `django.contrib.auth.forms` 中的用户名、电子邮件和密码字段的小部件中添加了 HTML `autocomplete` 属性，以更好地与浏览器密码管理器交互。

- `createsuperuser` 现在在非交互模式下，当没有提供相应的命令行参数时，会回退到环境变量来获取密码和必填字段。

- `REQUIRED_FIELDS` 现在支持 `ManyToManyField`。

- 新的 `UserManager.with_perm()` 方法返回具有指定权限的用户。

- PBKDF2 密码哈希器的默认迭代次数从 150 , 000 增加到 180 , 000 。

#### `django.contrib.gis`

- 允许 MySQL 空间查询函数在真实几何对象上操作。之前的支持仅限于边界框。

- 添加了 `GeometryDistance` 函数，在 PostGIS 上支持。

- 在 `Distance` 中添加了对 `furlong` 单位的支持。

- `GEOIP_PATH` 设置现在支持 `pathlib.Path`。

- `GeoIP2` 类现在接受 `pathlib.Path` 的 `path`。

#### `django.contrib.postgres`

- 新的 `RangeOperators` 有助于避免在可以与 `RangeField` 一起使用的 SQL 运算符中出现拼写错误。

- 新的 `RangeBoundary` 表达式表示范围的边界。

- 新的 `AddIndexConcurrently` 和 `RemoveIndexConcurrently` 类允许在 PostgreSQL 上使用 `CONCURRENTLY` 创建和删除索引。

#### `django.contrib.sessions`

- The new `get_session_cookie_age()` method allows dynamically specifying the session cookie age.

#### `django.contrib.syndication`

- Added the `language` class attribute to the `django.contrib.syndication.views.Feed` to customize a feed language. The default value is `get_language()` instead of `LANGUAGE_CODE`.

#### 缓存

- `add_never_cache_headers()` 和 `never_cache()` 现在在 `Cache-Control` 头中添加了 `private` 指令。

#### 文件存储

- 新的 `Storage.get_alternative_name()` 方法允许自定义生成文件名的算法，如果已经存在具有上传名称的文件。

#### 表单

- Formsets may control the widget used when ordering forms via `can_order` by setting the `ordering_widget` attribute or overriding `get_ordering_widget`.

#### 国际化

- 添加了 `LANGUAGE_COOKIE_HTTPONLY`、`LANGUAGE_COOKIE_SAMESITE` 和 `LANGUAGE_COOKIE_SECURE` 设置，用于在语言 cookie 上设置 `HttpOnly`、`SameSite` 和 `Secure` 标志。这些设置的默认值保留了以前的行为。

- 增加了对乌兹别克语的支持和翻译。

#### 日志

- `AdminEmailHandler` 的新参数 `reporter_class` 允许提供一个 `django.views.debug.ExceptionReporter` 的子类，以自定义在 `DEBUG` 为 `False` 时发送给站点 `ADMINS` 的异常回溯文本。

#### 管理命令

- 新的 `compilemessages --ignore` 选项允许在搜索要编译的 `.po` 文件时忽略特定目录。

- `showmigrations --list` 在 `--verbosity` 为 2 及以上时现在会显示已应用的日期时间。

- 在 PostgreSQL 上，`dbshell` 现在支持客户端端的 TLS 证书。

- `inspectdb` 现在在外键具有唯一或主键约束时会检查 `OneToOneField`。

- 新的 `--skip-checks` 选项在运行命令之前跳过运行系统检查。

- `startapp --template` 和 `startproject --template` 选项现在支持存储在 XZ 存档（`.tar.xz`、`.txz`）和 LZMA 存档（`.tar.lzma`、`.tlz`）中的模板。

#### 模型

- 添加了哈希数据库函数 `MD5`、`SHA1`、`SHA224`、`SHA256`、`SHA384` 和 `SHA512`。

- 添加了 `Sign` 数据库函数。

- `Trunc` 数据库函数的新参数 `is_dst` 决定了不存在和模糊的日期时间的处理方式。

- `connection.queries` 现在在 PostgreSQL 上显示 `COPY … TO` 语句。

- `FilePathField` 现在接受可调用对象作为 `path`。

- 允许自引用 `ManyToManyField` 的对称中间表。

- `CheckConstraint`、`UniqueConstraint` 和 `Index` 的 `name` 属性现在支持使用 `'%(app_label)s'` 和 `'%(class)s'` 占位符进行应用标签和类插值。

- The new `Field.descriptor_class` attribute allows model fields to customize the get and set behavior by overriding their descriptors.

- `Avg` 和 `Sum` 现在支持 `distinct` 参数。

- 添加了 `SmallAutoField`，它的行为类似于 `AutoField`，但它只允许在某个（与数据库相关的）限制内的值。在Django支持的所有数据库中，值从 `1` 到 `32767` 都是安全的。

- `AutoField`、`BigAutoField` 和 `SmallAutoField` 现在分别继承自 `IntegerField`、`BigIntegerField` 和 `SmallIntegerField`。系统检查和验证器现在也会正确继承。

- `FileField.upload_to` 现在支持 `pathlib.Path`。

- `CheckConstraint` 现在在 MySQL 8.0.16+ 上受支持。

- `django.db.backends.base.BaseDatabaseFeatures` 的新方法 `allows_group_by_selected_pks_on_model()` 允许优化 `GROUP BY` 子句，只需要选定的模型主键。默认情况下，它仅在 PostgreSQL 上支持托管的模型。

  要启用针对未托管模型的 `GROUP BY` 主键优化，您需要子类化 PostgreSQL 数据库引擎，并根据需要覆盖 features 类的 `allows_group_by_selected_pks_on_model()` 方法。有关示例，请参阅 子类化内置数据库后端。

#### 请求和响应

- 允许使用 `memoryview` 内容初始化 `HttpResponse`。

- 例如，在 Django 模板中，现在允许使用下划线（例如，`user_agent`）来查找 `HttpRequest.headers`，而不是连字符。

#### 安全

- `X_FRAME_OPTIONS` 现在默认为 `'DENY'`。在较旧的版本中，`X_FRAME_OPTIONS` 设置默认为 `'SAMEORIGIN'`。如果您的站点使用自身的框架，您将需要显式设置 `X_FRAME_OPTIONS = 'SAMEORIGIN'`，以便它们继续正常工作。

- `SECURE_CONTENT_TYPE_NOSNIFF` 现在默认为 `True`。启用此选项后，`SecurityMiddleware` 会在所有尚未设置该标头的响应上设置 X-Content-Type-Options: nosniff 标头。

- `SecurityMiddleware` 现在可以发送 Referrer-Policy 标头。

#### 测试

- 新的测试 `Client` 参数 `raise_request_exception` 允许控制请求期间引发的异常是否也应该在测试中引发。默认情况下，该值为 `True`，以保持向后兼容性。如果它为 `False` 并且发生异常，测试客户端将返回一个带有属性 `exc_info` 的 500 响应，该属性是一个元组，提供了发生的异常信息。

- 可以使用新的 `test -k` 选项通过测试名称模式选择要运行的测试和测试用例。

- HTML 比较，如 `assertHTMLEqual()` 所使用的，现在将相同字符引用的文本、字符引用和实体引用视为等效。

- `DiscoverRunner` 现在可以使用 `test --pdb` 选项在每个错误或失败时启动调试器。

## 3.0 版本中的不向后兼容的更改。

### 在提供主键默认值时，使用 `Model.save()`

`Model.save()` 在保存新的 `Model` 实例并提供主键的默认值时不再尝试查找行，而总是执行单个 `INSERT` 查询。在较早的 Django 版本中，`Model.save()` 根据行是否存在执行了 `INSERT` 或 `UPDATE`。

这使得在提供默认主键值的情况下调用 `Model.save()` 等效于将 force_insert=True 传递给模型的 `save()`。尝试使用新的 `Model` 实例更新现有行将导致 `IntegrityError`。

要更新特定主键值的现有模型，请使用 `update_or_create()` 方法或 `QuerySet.filter(pk=…).update(…)`。例如：

    >>> MyModel.objects.update_or_create(pk=existing_pk, defaults={"name": "new name"})
    >>> MyModel.objects.filter(pk=existing_pk).update(name="new name")

### 数据库后端 API

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

- `DatabaseIntrospection.get_geometry_type()` 的第二个参数现在是行描述而不是列名。

- `DatabaseIntrospection.get_field_type()` 可能不再返回元组。

- 如果数据库可以在添加字段的同一 SQL 语句中创建外键，请添加适当的 SQL 到 `SchemaEditor.sql_create_column_inline_fk`；否则，请设置 `DatabaseFeatures.can_create_inline_fk = False`。

- `DatabaseFeatures.can_return_id_from_insert` 和 `can_return_ids_from_bulk_insert` 已更名为 `can_return_columns_from_insert` 和 `can_return_rows_from_bulk_insert`。

- 数据库函数现在在使用 `datetime.timedelta` 实例创建时处理 `datetime.timezone` 格式（例如 `timezone(timedelta(hours=5))`，这将输出 `'UTC+05:00'`）。第三方后端应在准备 `DateTimeField` 的 `datetime_cast_date_sql()`、`datetime_extract_sql()` 等时处理这种格式。

- 为了支持这些字段类型上的整数范围验证器，已经将 `AutoField`、`BigAutoField` 和 `SmallAutoField` 的条目添加到 `DatabaseOperations.integer_field_ranges` 中。第三方后端可能需要自定义默认条目。

- `DatabaseOperations.fetch_returned_insert_id()` 已被替换为 `fetch_returned_insert_columns()`，它返回由 `INSERT … RETURNING` 语句返回的值列表，而不是单个值。

- `DatabaseOperations.return_insert_id()` 已被替换为 `return_insert_columns()`，它接受一个 `fields` 参数，该参数是要在插入后返回的字段的可迭代对象。通常这只是自动生成的主键。

### `django.contrib.admin`

- 管理者模型历史更改消息现在更偏向于使用可读性更高的字段标签，而不是字段名称。

### `django.contrib.gis`

- 不再支持 PostGIS 2.1 。

- 不再支持 SpatiaLite 4.1 和 4.2 。

- 不再支持 GDAL 1.11 和 GEOS 3.4 。

### 不再支持 PostgreSQL 9.4 。

上游对于 PostgreSQL 9.4 的支持在 2019 年 12 月结束。 Django 3.0 支持 PostgreSQL 9.5 及更高版本。

### 不再支持 Oracle 12.1 。

Oracle 12.1 的上游支持将于 2021 年 7 月结束。 Django 2.2 将支持至 2022 年 4 月。 Django 3.0 正式支持 Oracle 12.2 和 18c 版本。

### 移除了私有的 Python 2 兼容 API 。

尽管在 Django 2.0 中移除了对 Python 2 的支持，但某些私有 API 未被移除，以便第三方应用程序在 Python 2 生命周期结束之前仍可继续使用它们。

由于我们预计在添加对 Django 3.0 的支持时，应用程序将放弃对 Python 2 的兼容性，因此我们此时正在移除这些 API 。

- `django.test.utils.str_prefix()` - 在 Python 3 中，字符串不再具有 'u' 前缀。

- `django.test.utils.patch_logger()` - 请改用 `unittest.TestCase.assertLogs()`。

- `django.utils.lru_cache.lru_cache()` - 是 `functools.lru_cache()` 的别名。

- `django.utils.decorators.available_attrs()` - 此函数返回 `functools.WRAPPER_ASSIGNMENTS`。

- `django.utils.decorators.ContextDecorator` - 是 `contextlib.ContextDecorator` 的别名。

- `django.utils._os.abspathu()` - 是 `os.path.abspath()` 的别名。

- `django.utils._os.upath()` 和 `npath()` - 在 Python 3 上不执行任何操作。

- `django.utils.six` - 移除对此库的使用或切换到 six。

- `django.utils.encoding.python_2_unicode_compatible()` - 是 `six.python_2_unicode_compatible()` 的别名。

- `django.utils.functional.curry()` - 请使用 `functools.partial()` 或 `functools.partialmethod`。请参阅 5b1c389603a353625ae1603ba345147356336afb。

- `django.utils.safestring.SafeBytes` - 自 Django 2.0 起未使用。

### `FILE_UPLOAD_PERMISSIONS` 设置的新默认值。

在较早的版本中，`FILE_UPLOAD_PERMISSIONS` 设置的默认值为 `None`。在默认的:setting:FILE_UPLOAD_HANDLERS 的情况下，这导致上传的文件根据其大小和使用的上传处理程序而具有不同的权限。

现在，默认情况下，`FILE_UPLOAD_PERMISSIONS` 默认为 `0o644`，以避免这种不一致性。

### 安全设置的新默认值。

为了使 Django 项目在默认情况下更加安全，一些安全设置现在具有更安全的默认值：

- `X_FRAME_OPTIONS` 现在默认为 `'DENY'`。

- `SECURE_CONTENT_TYPE_NOSNIFF` 现在默认为 `True`。

有关这些更改的更多详细信息，请参阅上面的 What's New Security section。

### 杂项

- `ContentType.__str__()` 现在包括模型的 `app_label` 以消除在不同应用程序中具有相同名称的模型的歧义。

- 由于已弃用在 cookie 中而不是会话中访问语言，因此 `LocaleMiddleware` 不再在会话中查找用户的语言，而 `django.contrib.auth.logout()` 在注销后不再保留会话的语言。

- `django.utils.html.escape()` 现在使用 `html.escape()` 来转义 HTML。这会将 `'` 转换为 `&#x27;`，而不是以前的等效十进制代码 `&#39;`。

- `django-admin test -k` 选项现在与 `unittest -k` 选项一样工作，而不再作为 `--keepdb` 的快捷方式。

- 对于 `pywatchman` 版本低于 1.2.0 的支持已被移除。

- 在 `doseq=False` 时，`urlencode()` 现在会像标准库的 `urllib.parse.urlencode()` 函数一样，将可迭代的值按原样编码，而不是迭代它们。

- `intword` 模板过滤器现在将 `1.0` 翻译为单数短语，将所有其他数值视为复数。这对某些语言可能不正确。

- 给模型的 `ForeignKey` 或 `OneToOneField` 的 `'_id'` 属性分配一个值现在会取消对应字段的设置。之后访问该字段将导致查询。

- `patch_vary_headers()` 现在按照 RFC 7231 Section 7.1.4 处理星号 `'*'`，即如果标头字段名称列表包含星号，则 `Vary` 标头将包含单个星号 `'*'`。

- 在 MySQL 8.0.16+ 上，`PositiveIntegerField` 和 `PositiveSmallIntegerField` 现在包括一个检查约束，以防止数据库中出现负值。

- `alias=None` 已添加到 `Expression.get_group_by_cols()` 的签名中。

- `RegexPattern`，由 `re_path()` 使用，不再返回带有 `None` 值的关键字参数，以便传递给视图，用于缺少的可选命名组。

## 在 3.0 中被废弃的功能

### `django.utils.encoding.force_text()` 和 `smart_text()`

`smart_text()` 和 `force_text()` 别名（自 Django 2.0 起）的 `smart_str()` 和 `force_str()` 已被弃用。如果您的代码支持 Python 2，请忽略此弃用，因为在 Python 2 中，`smart_str()` 和 `force_str()` 的行为是不同的。

### 杂项

- `django.utils.http.urlquote()`, `urlquote_plus()`, `urlunquote()`, 和 `urlunquote_plus()` 已被弃用，建议使用它们的别名函数：`urllib.parse.quote()`, `quote_plus()`, `unquote()`, 和 `unquote_plus()`。

- `django.utils.translation.ugettext()`, `ugettext_lazy()`, `ugettext_noop()`, `ungettext()`, 和 `ungettext_lazy()` 已被弃用，建议使用它们的别名函数：`django.utils.translation.gettext()`, `gettext_lazy()`, `gettext_noop()`, `ngettext()`, 和 `ngettext_lazy()`。

- 为了限制会话的创建，从而支持某些缓存策略，在 Django 4.0 中，`django.views.i18n.set_language()` 将停止在会话中设置用户的语言。自 Django 2.1 起，语言始终存储在 `LANGUAGE_COOKIE_NAME` cookie 中。

- `django.utils.text.unescape_entities()` 已被弃用，建议使用 `html.unescape()`。请注意，与 `unescape_entities()` 不同，`html.unescape()` 立即评估延迟字符串。

- 为了避免对有效范围的可能混淆，私有的内部实用程序 `is_safe_url()` 被重命名为 `url_has_allowed_host_and_scheme()`。通常情况下，一个 URL 具有允许的主机和方案并不意味着它是"安全的"。例如，它可能仍然被引用不正确。请确保在不受信任的 URL 的路径组件上也使用 `iri_to_uri()`。

## 在 3.0 版本中删除的功能。

这些功能已经完成了其弃用周期，并在 Django 3.0 中被移除。

有关这些更改的详细信息，包括如何移除对这些功能的使用，请参阅 在 2.0 中被废弃的功能。

- `django.db.backends.postgresql_psycopg2` 模块已被移除。

- `django.shortcuts.render_to_response()` 已被移除。

- `DEFAULT_CONTENT_TYPE` 设置已被移除。

- `HttpRequest.xreadlines()` 已被移除。

- `Field.from_db_value()` 和 `Expression.convert_value()` 的 `context` 参数支持已被移除。

- `QuerySet.earliest()` 和 `latest()` 的 `field_name` 关键参数已被移除。

请参阅 在 2.1 中被废弃的功能 以获取有关这些更改的详细信息，包括如何移除对这些功能的使用。

- `ForceRHR` GIS 函数已被移除。

- `django.utils.http.cookie_date()` 已被移除。

- `staticfiles` 和 `admin_static` 模板标签库已被移除。

- `django.contrib.staticfiles.templatetags.staticfiles.static()` 已被移除。