# Django 6.0.7 documentation

# Django 2.1 版本发行说明

2018 年 8 月 1 日

欢迎使用 Django 2.1 ！

这些发布说明涵盖了 新功能，以及从 Django 2.0 或更早版本升级时需要注意的 不兼容变更。我们已经 删除了一些功能，这些功能已经到达了他们的弃用周期的末端，并且我们已经 开始了一些功能的弃用过程。

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

## Python 兼容性

Django 2.1 supports Python 3.5, 3.6, and 3.7. Django 2.0 is the last version to support Python 3.4. We highly recommend and only officially support the latest release of each series.

## Django 2.1 的新特性是什么？

### 模型的“查看”权限

模型的 `Meta.default_permissions` 属性中添加了 "view" 权限。这些新权限将在运行 `migrate` 时自动创建。

这允许将用户赋予对管理员中的模型的只读访问权限。新增了 `ModelAdmin.has_view_permission()`。该实现是向后兼容的，不需要分配 "view" 权限以允许拥有 "change" 权限的用户编辑对象。

有一些 不兼容考虑。

### 次要特性

#### `django.contrib.admin`

- 现在，`ModelAdmin.search_fields` 接受任何查找，如 `field__exact`。

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

- 新的 `ModelAdmin.delete_queryset()` 方法允许自定义 "删除选定对象" 操作的删除过程。

- 现在你可以 覆盖默认的管理站点。

- 新的 `ModelAdmin.sortable_by` 属性和 `ModelAdmin.get_sortable_by()` 方法允许限制可以在更改列表页面中排序的列。

- 在 `ModelAdmin.list_display` 中的元素的 `admin_order_field` 属性现在可以是一个查询表达式。

- The new `ModelAdmin.get_deleted_objects()` method allows customizing the deletion process of the delete view and the "delete selected" action.

- `actions.html`、`change_list_results.html`、`date_hierarchy.html`、`pagination.html`、`prepopulated_fields_js.html`、`search_form.html` 和 `submit_line.html` 模板现在可以在每个应用程序或每个模型的基础上 被覆盖 （除了全局覆盖）。

- 管理员更改列表和更改表单对象工具现在可以在每个应用程序、每个模型或全局 被覆盖，使用 `change_list_object_tools.html` 和 `change_form_object_tools.html` 模板。

- `InlineModelAdmin.has_add_permission()` 现在将父对象作为第二个位置参数传递，`obj`。

- 管理员操作现在可以 指定权限 以限制它们对某些用户的可用性。

#### `django.contrib.auth`

- `createsuperuser` 现在会提示是否允许绕过 `AUTH_PASSWORD_VALIDATORS` 检查。

#### `django.contrib.gis`

- 新的 `GEOSGeometry.buffer_with_style()` 方法是 `buffer()` 的一个版本，允许自定义缓冲区的样式。

- `OpenLayersWidget` 现在基于 OpenLayers 4.6.5（之前是 3.20.1）。

#### `django.contrib.sessions`

- 添加了 `SESSION_COOKIE_SAMESITE` 设置，用于在会话 cookie 上设置 `SameSite` cookie 标志。

#### 缓存

- 本地内存缓存后端 现在使用最近最少使用（LRU）的淘汰策略，而不是伪随机策略。

- 低级缓存 API 的新方法 `touch()` 可以更新缓存键的超时时间。

#### CSRF

- 添加了 `CSRF_COOKIE_SAMESITE` 设置，用于在 CSRF cookie 上设置 `SameSite` cookie 标志。

#### 表单

- `ImageField` 的小部件现在以带有 HTML 属性 `accept="image/*"` 渲染。

#### 国际化

- 添加了 `get_supported_language_variant()` 函数。

- 领土语言变体的未翻译字符串现在使用通用语言的翻译。例如，未翻译的 `pt_BR` 字符串使用 `pt` 的翻译。

#### 管理命令

- 新的 `inspectdb --include-views` 选项允许为数据库视图创建模型。

- `BaseCommand` 类现在使用自定义的帮助格式化程序，以使标准选项如 `--verbosity` 或 `--settings` 出现在帮助输出的最后，从而为子类命令的选项提供更突出的位置。

#### 迁移

- 添加了对 `functools.partialmethod` 对象的序列化支持。

- 为了支持冻结的环境，迁移可以从 `.pyc` 文件中加载。

#### 模型

- 模型现在可以使用来自 PEP 487 的 `__init_subclass__()` 方法。

- 如果希望将它包含在模型表单中，可以将 `BinaryField` 设置为 `editable=True`。

- 新增了一些新的文本数据库函数：`Chr`、`Left`、`LPad`、`LTrim`、`Ord`、`Repeat`、`Replace`、`Right`、`RPad`、`RTrim` 和 `Trim`。

- 新的 `TruncWeek` 函数将 `DateField` 和 `DateTimeField` 截断到一周的星期一。

- 现在可以使用减号对查询表达式进行否定。

- `QuerySet.order_by()` 和 `distinct(*fields)` 现在支持使用字段变换。

- `BooleanField` 现在可以设置为 `null=True`。这是鼓励的，而不是使用 `NullBooleanField`，后者可能会在将来被弃用。

- 新的 `QuerySet.explain()` 方法显示查询集查询的数据库执行计划。

- `QuerySet.raw()` 现在支持 `prefetch_related()`。

#### 请求和响应

- 添加了 `HttpRequest.get_full_path_info()`。

- 添加了 `samesite` 参数到 `HttpResponse.set_cookie()` 以允许设置 `SameSite` cookie 标志。

- `FileResponse` 的新 `as_attachment` 参数设置了 `Content-Disposition` 头，使浏览器询问用户是否要下载文件。`FileResponse` 还会在适当的情况下尝试设置 `Content-Type` 和 `Content-Length` 头。

#### 模板

- 新的 `json_script` 过滤器安全地将 Python 对象输出为 JSON，包装在 `<script>` 标签中，可供 JavaScript 使用。

#### 测试

- 添加了对 307 和 308 重定向的测试支持，测试 `Client`。

- 测试 `Client` 现在如果 `content_type='application/json'`，会将请求数据字典序列化为 JSON。你可以通过测试客户端的 `json_encoder` 参数自定义 JSON 编码器。

- 新的 `SimpleTestCase.assertWarnsMessage()` 方法是 `assertWarnsRegex()` 的简化版本。

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

### 数据库后端 API

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

- 为了遵循 PEP 249，在数据库不支持某项功能时，异常已从 `NotImplementedError` 更改为 `django.db.NotSupportedError`。

- 将数据库特性标志 `allow_sliced_subqueries` 重命名为 `allow_sliced_subqueries_with_in`。

- `DatabaseOperations.distinct_sql()` 现在需要额外的 `params` 参数，并返回一个包含 SQL 和参数的元组，而不是一个 SQL 字符串。

- `DatabaseFeatures.introspected_boolean_field_type` 从方法更改为属性。

### `django.contrib.gis`

- 移除对 SpatiaLite 4.0 的支持。

### 不再支持 MySQL 5.5 版本

MySQL 5.5 的上游支持结束于 2018 年 12 月。 Django 2.1 支持 MySQL 5.6 及更高版本。

### 不再支持 PostgreSQL 9.3 版本

PostgreSQL 9.3 的上游支持结束于 2018 年 9 月。 Django 2.1 支持 PostgreSQL 9.4 及更高版本。

### 从默认的 `PASSWORD_HASHERS` 设置中移除了 `BCryptPasswordHasher`。

如果你在 Django 1.4 或 1.5 中使用了 bcrypt（在 Django 1.6 中添加了 `BCryptSHA256PasswordHasher`），你可能有一些使用了 `BCryptPasswordHasher` 哈希算法的密码。

您可以像这样检查是否符合条件：

    from django.contrib.auth import get_user_model

    User = get_user_model()
    User.objects.filter(password__startswith="bcrypt$$")

如果你想继续允许使用这些密码，你将需要定义 `PASSWORD_HASHERS` 设置（如果尚未定义），并包含 `'django.contrib.auth.hashers.BCryptPasswordHasher'`。

### 移动了 `wrap_label` 小部件模板上下文变量

为了解决在使用 `MultiWidget` 时使用 `RadioSelect` 和 `CheckboxSelectMultiple` 时缺少 `<label>` 的问题，现在 `wrap_label` 上下文变量已经作为每个选项的属性出现。例如，在自定义的 `input_option.html` 模板中，将 `{% if wrap_label %}` 更改为 `{% if widget.wrap_label %}`。

### `SameSite` cookies

用于 `django.contrib.sessions`、`django.contrib.messages` 和 Django 的 CSRF 保护的 cookie 现在默认将 `SameSite` 标志设置为 `Lax`。遵循此标志的浏览器不会在跨源请求上发送这些 cookie。如果依赖旧行为，请将 `SESSION_COOKIE_SAMESITE` 和/或 `CSRF_COOKIE_SAMESITE` 设置为 `None`。

### 新模型“查看”权限的注意事项

#### 自定义管理表单需要考虑只读视图的情况。

新的 "view" 权限引入后，已存在的自定义管理员表单可能会在用户没有 "change" 权限时引发错误，因为表单可能会访问不存在的字段。通过覆盖 `ModelAdmin.get_form()` 方法，可以解决此问题，检查用户是否具有 "change" 权限，如果没有，则返回默认表单：

    class MyAdmin(admin.ModelAdmin):
        def get_form(self, request, obj=None, **kwargs):
            if not self.has_change_permission(request, obj):
                return super().get_form(request, obj, **kwargs)
            return CustomForm

#### 新的默认视图权限可能会导致对管理员视图的非预期访问。

如果你有一个自定义权限，其代码名称的形式为 `view_<modelname>`，新的管理员中的视图权限处理将允许访问这些模型的 changelist 和详情页。如果这不是你想要的行为，你必须更改你的自定义权限代码名称。

### 杂项

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

- 不再支持 SQLite 版本低于 3.7.15 。

- `Set-Cookie` 的 `Expires` 指令的日期格式已更改，以遵循 RFC 7231 Section 7.1.1.1，而不是 Netscape 的 cookie 标准。在日期中出现的连字符（如 `Tue, 25-Dec-2018 22:26:13 GMT`）已被移除。这个改变应该只是视觉上的变化，除非是一些不支持新格式的过时浏览器。

- `allowed_hosts` 现在是私有 API `django.utils.http.is_safe_url()` 的必需参数。

- `SelectMultiple` 小部件渲染的 `multiple` 属性现在使用 HTML5 的布尔语法，而不是 XHTML 的 `multiple="multiple"`。

- 由表单小部件渲染的 HTML 不再在空元素上包含闭合斜杠，例如 `<br>`。这在 XHTML 中不兼容，尽管一些小部件已经使用了 HTML5 的一些特性，如布尔属性。

- `SelectDateWidget` 的空选项的值已从 0 更改为空字符串，这主要可能需要在比较 HTML 的测试中进行一些调整。

- `User.has_usable_password()` 和 `is_password_usable()` 函数不再在密码为 `None`、空字符串或使用不在 `PASSWORD_HASHERS` 设置中的哈希器时返回 `False`。这种未记录的行为是 Django 1.6 中的一个回归，阻止了使用这些密码的用户请求密码重置。审查你的代码以确认你的这些 API 的使用不依赖于旧的行为。

- 由于迁移现在从 `.pyc` 文件加载，如果你在混合 Python 2 和 Python 3 环境中工作，你可能需要删除它们。

- 在 `django.contrib.postgres.fields.JSONField` 上使用 `None` 作为查找值现在匹配具有指定键和空值的对象，而不是不具有该键的对象。

- 管理员的 CSS 类 `field-box` 已重命名为 `fieldBox`，以防止与模型字段命名为 "box" 的类发生冲突。

- 由于现在可以按应用程序或模型覆盖管理员的 `actions.html`、`change_list_results.html`、`date_hierarchy.html`、`pagination.html`、`prepopulated_fields_js.html`、`search_form.html` 和 `submit_line.html` 模板，因此您可能需要重命名已为不同目的编写的具有这些名称的现有模板。

- `QuerySet.raw()` 现在像常规的查询集一样缓存其结果。如果不想缓存，请使用 `iterator()`。

- 数据库路由器的 `allow_relation()` 方法在更多情况下被调用。不正确编写的路由器可能需要相应地进行更新。

- 在运行管理命令之前不再停用翻译。如果你的自定义命令需要停用翻译（例如，将未翻译的内容插入数据库），可以使用新的 @no_translations 装饰器。

- 管理命令不再允许 `--settings` 和 `--pythonpath` 参数的缩写形式。

- 私有常量 `django.db.models.sql.constants.QUERY_TERMS` 已被移除。 查找注册 API 的 `get_lookup()` 和 `get_lookups()` 方法可能是合适的替代方案。与 `QUERY_TERMS` 常量相比，它们允许您的代码还考虑了已注册的任何自定义查找。

- 与 `py-bcrypt` 的兼容性已被移除，因为它已不再维护。请改用 bcrypt。

## 在 2.1 中被废弃的功能

### 杂项

- `ForceRHR` GIS 函数已被弃用，建议使用新的 `ForcePolygonCW` 函数。

- `django.utils.http.cookie_date()` 已被弃用，建议使用 `http_date()`，它遵循最新 RFC 的格式。

- `{% load staticfiles %}` 和 `{% load admin_static %}` 已被弃用，建议使用 `{% load static %}`，它具有相同的功能。

- `django.contrib.staticfiles.templatetags.static()` 已被弃用，建议使用 `django.templatetags.static.static()`。

- 不接受 `obj` 作为第二个位置参数的 `InlineModelAdmin.has_add_permission()` 方法的支持将在 Django 3.0 中被移除。

## 在 2.1 版本中删除的功能

这些功能已经完成了其弃用周期，并在 Django 2.1 中被移除。有关详细信息，包括如何删除这些功能的用法，请参阅 在 1.11 中被废弃的功能。

- `contrib.auth.views.login()`, `logout()`, `password_change()`, `password_change_done()`, `password_reset()`, `password_reset_done()`, `password_reset_confirm()`, 和 `password_reset_complete()` 已被移除。

- `contrib.auth.views.logout_then_login()` 的 `extra_context` 参数已被移除。

- `django.test.runner.setup_databases()` 已被移除。

- `django.utils.translation.string_concat()` 已被移除。

- `django.core.cache.backends.memcached.PyLibMCCache` 不再支持将 `pylibmc` 行为设置作为 `OPTIONS` 的顶级属性传递。

- `django.utils.http.is_safe_url()` 的 `host` 参数已被移除。

- 不再屏蔽在渲染 `{% include %}` 模板标签时引发的异常。

- `DatabaseIntrospection.get_indexes()` 已被移除。

- 认证后端的 `authenticate()` 方法要求将 `request` 作为第一个位置参数。

- `django.db.models.permalink()` 装饰器已被移除。

- `USE_ETAGS` 设置已被移除。`CommonMiddleware` 和 `django.utils.cache.patch_response_headers()` 不再设置 ETags。

- `Model._meta.has_auto_field` 属性已被移除。

- `url()` 对正则表达式组中的内联标志（`(?i)`、`(?L)`、`(?m)`、`(?s)` 和 `(?u)`）的支持已被移除。

- 不再支持没有 `renderer` 参数的 `Widget.render()` 方法。