Django 4.1 版本发行说明¶
2022 年 8 月 3 日
欢迎使用 Django 4.1!
这些发布说明涵盖了 新功能,以及从 Django 4.0 或更早版本升级时需要注意的一些 不兼容变更。我们已经 开始了某些功能的弃用过程。
如果你要更新现有的项目,请看 如何将 Django 更新至新的版本 指南。
Python 兼容性¶
Django 4.1 支持 Python 3.8、3.9、3.10 和 3.11(从 4.1.3 开始)。我们 强烈建议 并且只官方支持每个系列的最新发布版本。
Django 4.1 新特性¶
基于类的视图的异步处理程序。¶
现在,视图的子类可以定义异步的 HTTP 方法处理程序:
import asyncio
from django.http import HttpResponse
from django.views import View
class AsyncView(View):
async def get(self, request, *args, **kwargs):
# Perform view logic using await.
await asyncio.sleep(1)
return HttpResponse("Hello async world!")
请参阅 异步类视图 以获取更多详细信息。
异步的 ORM 接口。¶
QuerySet
现在为所有数据访问操作提供了异步接口。这些接口的命名方式与现有的同步操作相同,但带有一个 a
前缀,例如 acreate()
、aget()
等等。
新的接口允许您编写异步代码,而无需将 ORM 操作包装在 sync_to_async()
中:
async for author in Author.objects.filter(name__startswith="A"):
book = await author.books.afirst()
值得注意的是,目前数据库操作仍然是同步的,但正在进行贡献工作,以将异步支持推向 SQL 编译器并集成异步数据库驱动程序。新的异步查询集接口目前为您封装了必要的 sync_to_async()
操作,将允许您的代码充分利用 ORM 异步支持的发展。
请参阅 异步查询 以获取详细信息和限制。
约束的验证¶
在 Meta.constraints
选项中定义的 Check
、unique
和 exclusion
约束现在在 模型验证 期间进行检查。
表单渲染的可访问性¶
为了帮助使用屏幕阅读器和其他辅助技术的用户,从这个版本开始提供了基于 <div>
的新表单模板。这些模板提供比旧模板更可访问的导航,并能够正确地将相关控件(如单选列表)分组到字段集中。
推荐使用新模板,并且在 Django 5.0 中,当在模板中输出表单时(如 {{ form }}
),新模板将成为默认的表单呈现样式。
为了方便采用新的输出样式,现在可以通过项目级别的 FORM_RENDERER
设置来配置默认的表单和表单集模板。
请查看 下面的表单部分 以获取完整的详细信息。
次要特性¶
django.contrib.admin
¶
管理员 深色模式 CSS 变量 现在应用在一个单独的样式表和模板块中。
提供自定义
FieldListFilter
子类的 ModelAdmin 列表过滤器 现在可以在使用__in
查询时控制查询字符串值的分隔符,用于多个值的过滤。管理员的
history view
现在支持分页。相关的小部件包装现在有一个指向对象修改表单的链接。
AdminSite.get_app_list()
方法现在允许更改管理员首页上应用程序和模型的顺序。
django.contrib.auth
¶
PBKDF2 密码哈希器的默认迭代次数从 320 , 000 增加到 390 , 000 。
RemoteUserBackend.configure_user()
方法现在允许将用户属性与远程系统(如 LDAP 目录)中的属性同步。
django.contrib.gis
¶
新的
GEOSGeometry.make_valid()
方法允许将无效的几何图形转换为有效的几何图形。GEOSGeometry.normalize()
的新参数clone
允许创建几何图形的归一化克隆。
django.contrib.postgres
¶
新的
BitXor()
聚合函数返回所有非空输入值的按位XOR
的int
值。SpGistIndex
现在在 PostgreSQL 14+ 上支持覆盖索引。ExclusionConstraint
现在在 PostgreSQL 14+ 上支持使用 SP-GiST 索引的覆盖排除约束。新的
DateTimeRangeField
和DecimalRangeField
的default_bounds
属性允许为列表和元组输入指定边界。ExclusionConstraint
现在允许使用OpClass()
表达式指定操作符类。
django.contrib.sitemaps
¶
默认的站点地图索引模板
<sitemapindex>
现在在可用时包括<lastmod>
时间戳,通过新的get_latest_lastmod()
方法。自定义站点地图索引模板应该根据调整后的 上下文变量 进行更新。
django.contrib.staticfiles
¶
ManifestStaticFilesStorage
现在会将 CSS 源映射引用的路径替换为它们的哈希版本。
数据库后端¶
第三方数据库后端现在可以使用
DatabaseFeatures.minimum_database_version
属性指定数据库的最低要求版本,它是一个元组(例如(10, 0)
表示 "10.0")。如果指定了最低版本,后端还必须实现DatabaseWrapper.get_database_version()
,该方法返回当前数据库版本的元组。后端的DatabaseWrapper.init_connection_state()
方法必须调用super()
以便进行版本检查。
表单¶
渲染表单时默认使用的模板,例如在模板中作为
{{ form }}
显示,现在可以在项目级别通过在提供给FORM_RENDERER
的类上设置form_template_name
来配置。Form.template_name
现在是一个属性,延迟到渲染器,但可以用一个字符串值覆盖,以指定每个表单类的模板名称。同样,可以通过匹配的
formset_template_name
渲染器属性来指定用于渲染表单集的默认模板。新的
div.html
表单模板引用了Form.template_name_div
属性,并与Form.as_div()
方法匹配,使用 HTML<div>
元素来渲染表单。推荐使用这种新的输出样式,而不是现有的
as_table()
、as_p()
和as_ul()
样式,因为模板实现了<fieldset>
和<legend>
来组合相关的输入,对屏幕阅读器用户更容易导航。从 Django 5.0 开始,基于 div 的输出将成为默认的渲染样式。
为了平稳过渡到新的
<div>
输出样式,提供了两个过渡性的表单渲染器类:django.forms.renderers.DjangoDivFormRenderer
和django.forms.renderers.Jinja2DivFormRenderer
,分别适用于 Django 和 Jinja2 模板后端。您可以通过
FORM_RENDERER
设置之一来应用其中之一。例如:FORM_RENDERER = "django.forms.renderers.DjangoDivFormRenderer"
一旦
<div>
输出样式成为默认样式(从 Django 5.0 开始),这些过渡渲染器将被弃用,并计划在 Django 6.0 中移除。届时可以删除FORM_RENDERER
声明。如果新的
<div>
输出样式不适用于您的项目,您应该定义一个渲染器子类,指定form_template_name
和formset_template_name
以适应您所需的样式,并相应地设置FORM_RENDERER
。例如,对于
as_p()
使用的<p>
输出样式,您可以定义一个表单渲染器设置,将form_template_name
设置为"django/forms/p.html"
,将formset_template_name
设置为"django/forms/formsets/p.html"
。新的
legend_tag()
允许通过label_tag()
的新tag
参数以<legend>
标签方式呈现字段标签。对于
modelformset_factory()
和inlineformset_factory()
,新的edit_only
参数允许防止创建新对象。媒体 的
js
和css
类属性现在允许使用可散列的对象,而不仅仅是路径字符串,只要这些对象实现了__html__()
方法(通常在使用html_safe()
装饰器时)。新的
BoundField.use_fieldset
和Widget.use_fieldset
属性有助于识别那些应该在<fieldset>
中与<legend>
一起分组的小部件。BaseFormSet
的 error_messages 参数现在允许通过传递'too_few_forms'
和'too_many_forms'
键来自定义无效表单数量的错误消息。IntegerField
、FloatField
和DecimalField
现在可以选择接受一个step_size
参数。这用于设置step
HTML 属性,并在表单提交时进行验证。
国际化¶
i18n_patterns()
函数现在支持同时包含脚本和区域的语言。
管理命令¶
makemigrations --no-input
现在记录默认答案和无法创建迁移的原因。新的
makemigrations --scriptable
选项将日志输出和输入提示重定向到stderr
,仅将生成的迁移文件的路径写入stdout
。新的
migrate --prune
选项允许从django_migrations
表中删除不存在的迁移。由
startproject
、startapp
、optimizemigration
、makemigrations
和squashmigrations
创建的 Python 文件现在如果在您的PATH
上存在black
命令,将会使用它进行格式化。新的
optimizemigration
命令允许优化迁移操作。
迁移¶
The new
RenameIndex
operation allows renaming indexes defined in theMeta.indexes
orindex_together
options.迁移自动检测器现在在重命名
Meta.indexes
中定义的索引时,生成RenameIndex
操作,而不是RemoveIndex
和AddIndex
。The migrations autodetector now generates
RenameIndex
operations instead ofAlterIndexTogether
andAddIndex
, when moving indexes defined in theMeta.index_together
to theMeta.indexes
.
模型¶
Window
表达式的order_by
参数现在可以接受对字段和转换的字符串引用。新的
CONN_HEALTH_CHECKS
设置允许启用对 持久数据库连接 进行健康检查,以减少失败的请求次数,例如在数据库服务器重新启动后。现在,当插入一行时违反唯一约束时,
QuerySet.bulk_create()
支持更新字段。这在 MariaDB、MySQL、PostgreSQL 和 SQLite 3.24+ 上都受支持。QuerySet.iterator()
现在支持在提供了chunk_size
参数的情况下预取相关对象。在旧版本中,不进行预取。Q
对象和查询集现在可以使用^
作为异或(XOR
)运算符进行组合。XOR
在 MariaDB 和 MySQL 上有本地支持。对于不支持XOR
的数据库,查询将被转换为使用AND
、OR
和NOT
的等效查询。新的 Field.non_db_attrs 属性允许自定义不影响列定义的字段属性。
在 PostgreSQL 上,
AutoField
、BigAutoField
和SmallAutoField
现在作为标识列(identity columns)创建,而不是带有序列的序列列(serial columns)。
请求和响应¶
HttpResponse.set_cookie()
现在支持timedelta
对象作为max_age
参数。
安全¶
新的
SECRET_KEY_FALLBACKS
设置允许提供一组值用于密钥轮换。SECURE_PROXY_SSL_HEADER
设置现在支持在头部值中以逗号分隔的协议列表。
信号¶
pre_delete
和post_delete
信号现在会分发删除的origin
。
模板¶
在包装
json_script
模板过滤器时,不再需要 HTML<script>
元素的id
属性。在开发环境中,当
DEBUG
为True
且未指定OPTIONS['loaders']
时,现在会启用cached template loader
。如果需要,您可以指定OPTIONS['loaders']
来覆盖这个设置。
测试¶
DiscoverRunner
现在支持在 macOS、Windows 和任何默认multiprocessing
启动方法为spawn
的系统上并行运行测试。django.test.TestCase
中标记为持久的嵌套原子块现在会引发RuntimeError
,与测试外部相同。SimpleTestCase.assertFormError()
和assertFormsetError()
现在支持直接传递表单/表单集对象。
URLs¶
新的
ResolverMatch.captured_kwargs
属性存储了从 URL 解析的捕获的关键字参数。新的
ResolverMatch.extra_kwargs
属性存储了传递给视图函数的额外关键字参数。
实用程序¶
SimpleLazyObject
现在支持加法操作。mark_safe()
现在保留懒惰对象。
验证器¶
新的
StepValueValidator
用于检查一个值是否是给定步长的整数倍。这个新的验证器用于表示数值的表单字段的新参数step_size
。
4.1 版本中的不兼容变更¶
数据库后端 API¶
本节介绍了第三方数据库后端可能需要的更改。
BaseDatabaseFeatures.has_case_insensitive_like
从True
改为False
,以反映大多数数据库的行为。DatabaseIntrospection.get_key_columns()
已被移除。请改用DatabaseIntrospection.get_relations()
。DatabaseOperations.ignore_conflicts_suffix_sql()
方法被替换为DatabaseOperations.on_conflict_suffix_sql()
,它接受fields
、on_conflict
、update_fields
和unique_fields
参数。DatabaseOperations.insert_statement()
方法的ignore_conflicts
参数被替换为接受django.db.models.constants.OnConflict
的on_conflict
参数。DatabaseOperations._convert_field_to_tz()
被替换为DatabaseOperations._convert_sql_to_tz()
,它接受sql
、params
和tzname
参数。DatabaseOperations
上的多个日期和时间方法现在接受sql
和params
参数,而不再接受field_name
,并返回包含一些 SQL 和要插入该 SQL 的参数的 2 元组。已更改的方法具有以下新签名:DatabaseOperations.date_extract_sql(lookup_type, sql, params)
DatabaseOperations.datetime_extract_sql(lookup_type, sql, params, tzname)
DatabaseOperations.time_extract_sql(lookup_type, sql, params)
DatabaseOperations.date_trunc_sql(lookup_type, sql, params, tzname=None)
DatabaseOperations.datetime_trunc_sql(self, lookup_type, sql, params, tzname)
DatabaseOperations.time_trunc_sql(lookup_type, sql, params, tzname=None)
DatabaseOperations.datetime_cast_date_sql(sql, params, tzname)
DatabaseOperations.datetime_cast_time_sql(sql, params, tzname)
django.contrib.gis
¶
移除对 GDAL 2.1 的支持。
移除对 PostGIS 2.4 的支持。
不再支持 PostgreSQL 10 。¶
PostgreSQL 10 的上游支持将在 2022 年 11 月结束。 Django 4.1 支持 PostgreSQL 11 及更高版本。
不再支持 MariaDB 10.2¶
MariaDB 10.2 的上游支持将在 2022 年 5 月结束。 Django 4.1 支持 MariaDB 10.3 及更高版本。
管理后台的变更列表搜索跨多值关系的变更¶
管理员 changelist 使用多个搜索词进行搜索现在在单个调用 filter()
中应用,而不是在连续的 filter()
调用中应用。
对于多值关系,这意味着来自相关模型的行必须匹配所有词项,而不是任何词项。例如,如果 search_fields
设置为 ['child__name', 'child__age']
,用户搜索 'Jamal 17'
,那么只有与一些名为 Jamal 的 17 岁孩子存在关系的父母行才会被返回,而不会返回仅仅因为有一个名为 Jamal 的更年轻或更年长的孩子以及其他一些 17 岁孩子的父母。
有关这种差异的更多讨论,请参阅 跨多值关联 主题。在 Django 4.0 及更早版本中,get_search_results()
遵循第二个示例查询,但这种未记录的行为导致了具有过多连接的查询。
未保存的模型实例的反向外键变更¶
为了统一与未保存的模型实例的多对多关系的行为,反向外键现在在调用未保存对象的 related managers
时会引发 ValueError
。
杂项¶
ForeignKey
、ManyToManyField
和GenericRelation
的相关管理器现在被缓存在它们所属的Model
实例上。这个变更在 Django 4.1.2 中被撤销了。DiscoverRunner
now returns a non-zero error code for unexpected successes from tests marked withunittest.expectedFailure()
.CsrfViewMiddleware
现在不再像在 DOM 中遮蔽 CSRF 令牌一样遮蔽 CSRF cookie。CsrfViewMiddleware
现在使用request.META['CSRF_COOKIE']
来存储未遮蔽的 CSRF 密钥,而不是遮蔽版本。这是一个未记录的、私有的 API。ModelAdmin.actions
和inlines
属性现在默认为空元组,而不是空列表,以防止意外的变更。在 CSS 表单媒体 的
<link>
标签中不再包含type="text/css"
属性。formset:added
和formset:removed
JavaScript 事件现在是纯 JavaScript 事件,不依赖于 jQuery。有关此更改的更多详细信息,请参阅 内联表单事件。未记录的
django.utils.log.log_response()
函数的exc_info
参数已被替换为exception
。未记录的
django.views.static.was_modified_since()
函数的size
参数已被移除。管理员注销界面现在使用
POST
请求。未记录的
InlineAdminFormSet.non_form_errors
属性已被替换为non_form_errors()
方法。这与BaseFormSet
保持一致。根据 上面,在开发中现在启用了缓存模板加载器。如果有必要,你可以指定
OPTIONS['loaders']
来覆盖这个设置。未记录的
django.contrib.auth.views.SuccessURLAllowedHostsMixin
混合类已被替换为RedirectURLMixin
。BaseConstraint
的子类必须实现validate()
方法,以允许这些约束用于验证。未记录的
URLResolver._is_callback()
、URLResolver._callback_strs
和URLPattern.lookup_str()
已被移动到django.contrib.admindocs.utils
。Model.full_clean()
方法现在将exclude
值转换为一个set
。最好将exclude
值作为一个set
传递给Model.clean_fields()
、Model.full_clean()
、Model.validate_unique()
和Model.validate_constraints()
方法。asgiref
的最小支持版本从 3.4.1 提高到 3.5.2。组合表达式不再在参数类型匹配时猜测
output_field
的不稳定行为。因此,解析数据库函数和组合表达式的output_field
现在可能会在混合类型的情况下崩溃。在这种情况下,你需要明确设置output_field
。makemessages
命令在不需要更新时不再更改.po
文件。在旧版本中,POT-Creation-Date
总是会被更新。
4.1 版本中弃用的功能¶
通过 GET 方式注销登录¶
通过 GET
请求注销到 内置的注销视图
已经不推荐使用。请改为使用 POST
请求。
如果您想保留 HTML 链接的用户体验,可以使用一个被样式化为链接的表单:
<form id="logout-form" method="post" action="{% url 'admin:logout' %}">
{% csrf_token %}
<button type="submit">{% translate "Log out" %}</button>
</form>
#logout-form {
display: inline;
}
#logout-form button {
background: none;
border: none;
cursor: pointer;
padding: 0;
text-decoration: underline;
}
杂项¶
对于扁平化的 URL 列表的站点地图索引模板的上下文已被弃用。自定义站点地图索引模板应该根据调整后的 上下文变量 进行更新,期望一个具有
location
和可选lastmod
属性的对象列表。CSRF_COOKIE_MASKED
过渡设置已移除。在 Python 3.6 及更高版本中,
django.utils.functional.cached_property()
的name
参数已被弃用,因为它不再必要。django.contrib.postgres.constraints.ExclusionConstraint
的opclasses
参数已被弃用,而应使用ExclusionConstraint.expressions
中的OpClass()
。要使用它,你需要在INSTALLED_APPS
中添加'django.contrib.postgres'
。在进行这些更改后,
makemigrations
将生成一个新的迁移,其中包含两个操作:RemoveConstraint
和AddConstraint
。由于这些更改不影响数据库架构,可以使用SeparateDatabaseAndState
操作来仅更新迁移状态而不运行任何 SQL。将生成的操作移动到SeparateDatabaseAndState
的state_operations
参数中。例如:class Migration(migrations.Migration): ... operations = [ migrations.SeparateDatabaseAndState( database_operations=[], state_operations=[ migrations.RemoveConstraint(...), migrations.AddConstraint(...), ], ), ]
未记录的能够将
errors=None
传递给SimpleTestCase.assertFormError()
和assertFormsetError()
已被弃用。请改用errors=[]
。由于存在远程代码执行的风险,
django.contrib.sessions.serializers.PickleSerializer
已被弃用。在没有提供
chunk_size
参数的情况下,对预取相关对象的查询集使用QuerySet.iterator()
的用法已被弃用。在旧版本中,不会进行预取。提供chunk_size
的值表示希望每个块所需的预取额外查询。将未保存的模型实例传递给相关的过滤器已被弃用。在 Django 5.0 中,将引发异常。
RemoteUserBackend.configure_user()
的签名中添加了created=True
。不接受此参数的RemoteUserBackend
子类的支持已被弃用。别名
django.utils.timezone.utc
到datetime.timezone.utc
的使用已经被弃用。请直接使用datetime.timezone.utc
。在
SimpleTestCase.assertFormError()
和assertFormsetError()
中传递响应对象和表单/表单集名称已被弃用。请使用以下方式:assertFormError(response.context["form_name"], ...) assertFormsetError(response.context["formset_name"], ...)
或者直接传递表单/表单集对象。
未记录的
django.contrib.gis.admin.OpenLayersWidget
模块已被弃用。django.contrib.auth.hashers.CryptPasswordHasher
已废弃。在
Expression.asc()
和Expression.desc()
方法以及OrderBy
表达式中传递nulls_first=False
或nulls_last=False
的能力已被弃用。请改用None
。"django/forms/default.html"
和"django/forms/formsets/default.html"
模板,它们是表格模板的代理,已被弃用。请使用具体的模板。未记录的
LogoutView.get_next_page()
方法已被重命名为get_success_url()
。
在 4.1 版本中移除的功能¶
这些功能已经结束了其弃用周期,并在 Django 4.1 中被移除。
有关这些更改的详细信息,包括如何删除对这些功能的使用,请参阅 在 3.2 中被废弃的功能。
不再支持将不支持使用
copy.deepcopy()
创建深层副本的对象分配给TestCase.setUpTestData()
中的类属性。不再支持在
BaseCommand.requires_system_checks
中使用布尔值。django.core.validators.EmailValidator
的whitelist
参数和domain_whitelist
属性已被移除。default_app_config
应用程序配置变量已被移除。TransactionTestCase.assertQuerysetEqual()
在与字符串值进行比较时不再调用repr()
方法来处理查询集。django.core.cache.backends.memcached.MemcachedCache
已被移除。对
django.contrib.messages.storage.cookie.CookieStorage
使用的 Django 3.2 之前的消息格式的支持已被移除。