# Django 5.2.8 documentation

# Django 5.1 版本发行说明

2024 年 8 月 7 日

欢迎使用 Django 5.1！

这些发布说明涵盖了 新功能，以及从 Django 5.0 或更早版本升级时应注意的一些 不兼容的更改。我们已经 开始对一些功能进行弃用处理。

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

## Python 兼容性

Django 5.1 支持 Python 3.10、3.11、3.12 和 3.13（截至 5.1.3）。我们 强烈建议 并且仅官方支持每个系列的最新版本。

## Django 5.1 新特性

### `{% querystring %}` 模版标签

Django 5.1 引入了 `{% querystring %}` 模板标签，简化了 URL 中查询参数的修改，使得生成在添加或更改特定参数的同时保持现有查询参数的链接变得更加容易。

例如，在模板中处理分页和查询字符串可能会很繁琐。考虑以下模板片段，它动态生成了一个用于在分页视图中导航到下一页的 URL：

    {# Linebreaks added for readability, this should be one, long line. #}
    <a href="?{% for key, values in request.GET.iterlists %}
      {% if key != "page" %}
        {% for value in values %}
          {{ key }}={{ value }}&amp;
        {% endfor %}
      {% endif %}
    {% endfor %}page={{ page.next_page_number }}">Next page</a>

当切换到使用这个新的模板标签时，上面的代码神奇地变成了：

    <a href="{% querystring page=page.next_page_number %}">Next page</a>

### PostgreSQL 连接池

Django 5.1 还引入了对 PostgreSQL 的 连接池 支持。由于建立新连接的时间可能相对较长，保持连接打开可以减少延迟。

要使用 psycopg 的连接池，你可以在 `OPTIONS` 中将 `"pool"` 选项设置为一个字典，传递给 `ConnectionPool`，或者设置为 `True` 以使用 `ConnectionPool` 的默认值：

    DATABASES = {
        "default": {
            "ENGINE": "django.db.backends.postgresql",
            # ...
            "OPTIONS": {
                "pool": {
                    "min_size": 2,
                    "max_size": 4,
                    "timeout": 10,
                }
            },
        },
    }

### 默认情况下需要身份验证的中间件

新的 `LoginRequiredMiddleware` 将所有未经身份验证的请求重定向到登录页面。视图可以使用新的 `login_not_required()` 装饰器来允许未经身份验证的请求。

`LoginRequiredMiddleware` 尊重通过 `login_required()` 装饰器设置的 `login_url` 和 `redirect_field_name` 值，但不支持通过 `LoginRequiredMixin` 设置 `login_url` 或 `redirect_field_name`。

要启用此功能，请将 `"django.contrib.auth.middleware.LoginRequiredMiddleware"` 添加到你的 `MIDDLEWARE` 设置中。

### 次要特性

#### `django.contrib.admin`

- `ModelAdmin.list_display` 现在支持使用 `__` 查找来列出相关模型的字段。

#### `django.contrib.auth`

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

- `ScryptPasswordHasher` 的默认 `parallelism` 从 1 增加到 5，以遵循 OWASP 的建议。

- 新的 `AdminUserCreationForm` 和现有的 `AdminPasswordChangeForm` 现在支持通过在表单保存时设置不可用密码来禁用基于密码的身份验证。现在在访问用户创建和密码更改页面时，管理界面中也提供了此功能。

- `login_required()`、`permission_required()` 和 `user_passes_test()` 装饰器现在支持包装异步视图函数。

- `ReadOnlyPasswordHashWidget` 现在包含一个重置用户密码的按钮，取代了之前嵌入在 `ReadOnlyPasswordHashField` 帮助文本中的链接，从而提高了 `UserChangeForm` 的整体可访问性。

#### `django.contrib.gis`

- `BoundingCircle` 现在在 SpatiaLite 5.1+ 上受支持。

- `Collect` 现在在 MySQL 8.0.24+ 上受支持。

- `GeoIP2` 现在允许使用 `ipaddress.IPv4Address` 或 `ipaddress.IPv6Address` 对象进行查询。

- `GeoIP2.country()` 现在暴露了 `continent_code`、`continent_name` 和 `is_in_european_union` 值。

- `GeoIP2.city()` 现在暴露了 `accuracy_radius` 和 `region_name` 值。此外，`dma_code` 和 `region` 值现在分别暴露为 `metro_code` 和 `region_code`，但为了向后兼容，之前的键仍然保留。

- `Area` 现在支持 `ha` 单位。

- 新的 `OGRGeometry.is_3d` 属性允许检查几何体是否具有 `Z` 坐标维度。

- 新的 `OGRGeometry.set_3d()` 方法允许添加和移除 `Z` 坐标维度。

- `OGRGeometry`、`Point`、`LineString`、`Polygon` 和 `GeometryCollection` 及其子类现在通过新的 `OGRGeometry.is_measured` 和 `m` 属性以及 `OGRGeometry.set_measured()` 方法支持测量几何体。

- `OGRGeometry.centroid` 现在在所有支持的几何体类型上都可用。

- `FromWKB()` 和 `FromWKT()` 函数现在支持可选的 `srid` 参数（除了 Oracle，该参数被忽略）。

#### `django.contrib.postgres`

- `BTreeIndex` 现在支持 `deduplicate_items` 参数。

#### `django.contrib.sessions`

- `django.contrib.sessions.backends.cached_db.SessionStore` 现在处理在缓存中存储会话信息时的异常，通过新添加的 sessions logger 记录适当的错误信息及其回溯。

- `django.contrib.sessions.backends.base.SessionBase` 和所有内置的会话引擎现在提供了异步 API。新的异步方法都以 `a` 前缀命名，例如 `aget()`、`akeys()` 或 `acycle_key()`。

#### 数据库后端

- `"init_command"` 选项现在在 SQLite 的 `OPTIONS` 中受支持，允许指定在连接时设置的 pragma options。

- `"transaction_mode"` 选项现在在 SQLite 的 `OPTIONS` 中受支持，允许指定 事务行为。

- `"pool"` 选项现在在 PostgreSQL 的 `OPTIONS` 中受支持，允许使用 connection pools。

#### 错误报告

- 为了提高可访问性，技术性的 404 和 500 错误页面现在对页眉、页脚和主要内容区域使用 HTML 地标元素。

#### 文件存储

- `FileSystemStorage` 的 `allow_overwrite` 参数现在允许将新文件保存到现有文件上。

#### 表单

- 为了提高可访问性并使屏幕阅读器能够将字段集与其帮助文本关联起来，表单字段集现在包含 `aria-describedby` HTML 属性。

#### 管理命令

- `makemigrations` 命令现在为每个操作显示有意义的符号，以突出显示 `操作类别`。

#### 迁移

- 新的 `Operation.category` 属性允许指定 `makemigrations` 使用的 `操作类别`，以便为操作显示有意义的符号。

#### 模型

- `QuerySet.explain()` 现在在 PostgreSQL 16+ 上支持 `generic_plan` 选项。

- `RowRange` 现在接受 `start` 参数的正整数和 `end` 参数的负整数。

- `RowRange` 和 `ValueRange` 的新 `exclusion` 参数允许从窗口框架中排除行、组和并列项。

- `QuerySet.order_by()` 现在支持通过注解转换（如 `JSONObject` 键和 `ArrayAgg` 索引）进行排序。

- 输出 `CharField`、`EmailField`、`SlugField`、`URLField`、`TextField` 或 `ArrayField` 的 `F()` 和 `OuterRef()` 表达式现在可以 切片。

- `Model.refresh_from_db()` 和 `Model.arefresh_from_db()` 的新 `from_queryset` 参数允许自定义用于重新加载模型值的查询集。这可以用于在重新加载之前锁定行或选择相关对象。

- 新的 `Expression.constraint_validation_compatible` 属性允许指定在约束验证期间忽略该表达式。

#### 模板

- 自定义标签现在可以在 `Parser` 对象上设置额外的数据，这些数据稍后将在 `Template` 实例上可用。例如，模板加载器或其他模板客户端可以使用这些数据。

- 模板引擎 现在实现了一个 `check()` 方法，该方法已经注册到检查框架中。

#### 测试

- `assertContains()`、`assertNotContains()` 和 `assertInHTML()` 断言现在将干草堆添加到断言错误消息中。

- `RequestFactory`、`AsyncRequestFactory`、`Client` 和 `AsyncClient` 类现在支持 `query_params` 参数，该参数接受查询字符串键和值的字典。这使得在任何 HTTP 方法上设置查询字符串变得更加容易。

      self.client.post("/items/1", query_params={"action": "delete"})
      await self.async_client.post("/items/1", query_params={"action": "delete"})

- 新的 `SimpleTestCase.assertNotInHTML()` 断言允许测试给定的 HTML 干草堆中不包含某个 HTML 片段。

- 为了强制测试隔离，`SimpleTestCase` 中不再允许在线程内使用数据库连接。

#### 验证器

- 新的 `DomainNameValidator` 验证域名，包括国际化域名。新的 `validate_domain_name()` 函数返回 `DomainNameValidator` 的实例。

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

### `django.contrib.gis`

- 移除对 PostGIS 2.5 的支持。

- 已移除对 `PROJ` 版本低于 6 的支持。

- 移除对 GDAL 2.4 的支持。

- `GeoIP2` 在提供目录路径时不再同时打开城市和国家数据库，而是优先使用城市数据库（如果可用）。国家数据库是城市数据库的子集，通常不需要同时使用两者。如果你需要在与城市数据库相同的目录中使用国家数据库，请显式地将国家数据库路径传递给构造函数。

### 不再支持 MariaDB 10.4

上游对 MariaDB 10.4 的支持将于 2024 年 6 月结束。Django 5.1 支持 MariaDB 10.5 及更高版本。

### 不再支持 PostgreSQL 12

上游对 PostgreSQL 12 的支持将于 2024 年 11 月结束。Django 5.1 支持 PostgreSQL 13 及更高版本。

### 杂项

- 为了提高可访问性，管理界面的变更列表过滤器现在在 `<nav>` 标签中渲染，而不是 `<div>`。

- 为了提高可访问性，管理界面的页脚现在在 `<footer>` 标签中渲染，而不是 `<div>`，并且移动到 `<div id="main">` 元素下方。

- 为了提高可访问性，当字段集有名称并使用 `collapse` 类时，用于 `ModelAdmin.fieldsets` 和 `InlineModelAdmin.fieldsets` 的可展开小部件现在包含 `<details>` 和 `<summary>` 元素。

- JavaScript 文件 `collapse.js` 已被移除，因为它在 Django 管理站点中不再需要。

- `SimpleTestCase.assertURLEqual()` 和 `assertInHTML()` 现在在 `msg_prefix` 中添加 `": "`。这与其他断言的行为一致。

- `django.utils.text.Truncator` used by `truncatechars_html` and `truncatewords_html` template filters now uses `html.parser.HTMLParser` subclasses. This results in a more robust and faster operation, but there may be small differences in the output.

- 未记录的 `django.urls.converters.get_converter()` 函数已被移除。

- SQLite 的最低支持版本从 3.27.0 提高到 3.31.0。

- `FileField` 现在在保存没有 `name` 的文件时会引发 `FieldError`。

- `ImageField.update_dimension_fields(force=True)` 在将图像保存到存储后不再调用。如果你的存储后端调整了图像大小，`width_field` 和 `height_field` 将与图像的宽度和高度不匹配。

- `asgiref` 的最低支持版本从 3.7.0 提高到 3.8.1。

- To improve performance, the `delete_selected` admin action now uses `QuerySet.bulk_create()` when creating multiple `LogEntry` objects. As a result, `pre_save` and `post_save` signals for `LogEntry` are not sent when multiple objects are deleted via this admin action.

## 在 5.1 版本中废弃的功能

### 杂项

- `ModelAdmin.log_deletion()` 和 `LogEntryManager.log_action()` 方法已被弃用。子类应实现 `ModelAdmin.log_deletions()` 和 `LogEntryManager.log_actions()`。

- 未记录的 `django.utils.itercompat.is_iterable()` 函数和 `django.utils.itercompat` 模块已被弃用。请使用 `isinstance(..., collections.abc.Iterable)` 代替。

- `django.contrib.gis.geoip2.GeoIP2.coords()` 方法已被弃用。请使用 `django.contrib.gis.geoip2.GeoIP2.lon_lat()` 代替。

- `django.contrib.gis.geoip2.GeoIP2.open()` 方法已被弃用。请使用 `GeoIP2` 构造函数代替。

- 在 `Model.save()` 和 `Model.asave()` 中传递位置参数已被弃用，建议仅使用关键字参数。

- 设置 `django.contrib.gis.gdal.OGRGeometry.coord_dim` 已被弃用。请使用 `set_3d()` 代替。

- 不推荐使用 `django.urls.register_converter()` 覆盖现有的转换器。

- `CheckConstraint` 的 `check` 关键字参数已被弃用，建议使用 `condition`。

- 未记录的 `FileSystemStorage` 的 `OS_OPEN_FLAGS` 属性已被弃用。要允许覆盖存储中的文件，请将新的 `allow_overwrite` 选项设置为 `True`。

- `FieldCacheMixin` 的 `get_cache_name()` 方法已被弃用，建议使用 `cache_name` 缓存属性。

## 在 5.1 版本中移除的功能

这些功能已达到其弃用周期的末尾，并在 Django 5.1 中被移除。

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

- `BaseUserManager.make_random_password()` 方法已被移除。

- 模型的 `Meta.index_together` 选项已被移除。

- `length_is` 模板过滤器已被移除。

- `django.contrib.auth.hashers.SHA1PasswordHasher`、`django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher` 和 `django.contrib.auth.hashers.UnsaltedMD5PasswordHasher` 已被移除。

- `django.contrib.postgres.fields.CICharField`、`django.contrib.postgres.fields.CIEmailField` 和 `django.contrib.postgres.fields.CITextField` 模型已被移除，仅支持历史迁移。

- `django.contrib.postgres.fields.CIText` 混入类已被移除。

- `BaseGeometryWidget` 的 `map_width` 和 `map_height` 属性已被移除。

- `SimpleTestCase.assertFormsetError()` 方法已被移除。

- `TransactionTestCase.assertQuerysetEqual()` 方法已被移除。

- 支持将编码的 JSON 字符串字面量传递给 `JSONField` 及相关查找和表达式的功能已被移除。

- 支持将位置参数传递给 `Signer` 和 `TimestampSigner` 的功能已被移除。

- `DEFAULT_FILE_STORAGE` 和 `STATICFILES_STORAGE` 设置已被移除。

- `django.core.files.storage.get_storage_class()` 函数已被移除。