Django 4.0 版本发行说明¶
2021 年 12 月 7 日
欢迎使用 Django 4.0 !
这些发布说明涵盖了 新功能,以及从 Django 3.2 或更早版本升级时需要注意的一些 不向后兼容的变更。我们已经 开始了一些功能的弃用过程。
如果你要更新现有的项目,请看 如何将 Django 更新至新的版本 指南。
Python 兼容性¶
Django 4.0 支持 Python 3.8、3.9 和 3.10。我们 强烈建议 并只官方支持每个系列的最新版本。
Django 3.2.x 系列是最后一个支持 Python 3.6 和 3.7 的版本。
Django 4.0 新特性¶
zoneinfo
默认时区实现¶
Python 标准库的 zoneinfo
现在是 Django 中默认的时区实现。
这是从使用 pytz
到使用 zoneinfo
迁移的下一步。Django 3.2 允许使用非 pytz
时区。Django 4.0 将 zoneinfo
作为默认实现。对于 pytz
的支持现在已经不推荐使用,并将在 Django 5.0 中移除。
zoneinfo
是自 Python 3.9 起的 Python 标准库的一部分。如果你正在使用 Python 3.8,那么 backports.zoneinfo
包会在安装 Django 时自动安装。
迁移到 zoneinfo
应该在很大程度上是透明的。选择当前时区、在表单和模板中将日期时间实例转换为当前时区,以及在 UTC 中进行的带时区日期时间的操作都不受影响。
然而,如果你正在使用非 UTC 时区,并使用 pytz
的 normalize()
和 localize()
API,可能还涉及到 TIME_ZONE
设置,那么你需要审查你的代码,因为``pytz`` 和 zoneinfo
并不完全等同。
为了给这样的审核留出时间,过渡性的 USE_DEPRECATED_PYTZ
设置允许在 4.x 发布周期内继续使用 pytz
。这个设置将在 Django 5.0 中移除。
此外,zoneinfo
的作者创建了一个名为 pytz_deprecation_shim 的包,可用于协助从 pytz
迁移。这个包提供了帮助你安全移除 pytz
的 shims,并有一个详细的 迁移指南,展示了如何切换到新的 zoneinfo
API。
如果需要逐步更新路径,建议使用 pytz_deprecation_shim 和过渡性的 USE_DEPRECATED_PYTZ
设置。
函数式唯一约束¶
UniqueConstraint()
的新的 *expressions
位置参数允许在表达式和数据库函数上创建功能性的唯一约束。例如:
from django.db import models
from django.db.models import UniqueConstraint
from django.db.models.functions import Lower
class MyModel(models.Model):
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
class Meta:
constraints = [
UniqueConstraint(
Lower("first_name"),
Lower("last_name").desc(),
name="first_last_name_unique",
),
]
功能性唯一约束是通过在模型中使用 Meta.constraints
选项来添加的。
scrypt
密码哈希器¶
新的 scrypt 密码哈希器 更安全,推荐使用,但它不是默认选项,因为它需要 OpenSSL 1.1+ 和更多内存。
Redis 缓存后端¶
新的 django.core.cache.backends.redis.RedisCache
缓存后端提供了内置的支持,用于使用 Redis 进行缓存。需要 redis-py 的版本为 3.0.0 或更高。更多详情请参阅 Django 中关于使用 Redis 进行缓存的 文档。
基于模板的表单渲染¶
Forms
、Formsets 和 ErrorList
现在使用模板引擎进行渲染,以增强自定义功能。查看 Form
的新方法 render()
、get_context()
和 template_name
,以及关于 Formset
的 formset 渲染。
次要特性¶
django.contrib.admin
¶
admin/base.html
模板现在有一个新的块header
,其中包含了管理站点的标题。新的
ModelAdmin.get_formset_kwargs()
方法允许自定义传递给表单集构造函数的关键字参数。导航侧边栏现在有一个快速筛选工具栏。
新的上下文变量
model
包含了每个模型的模型类,已添加到AdminSite.each_context()
方法中。新的
ModelAdmin.search_help_text
属性允许指定搜索框的描述性文本。InlineModelAdmin.verbose_name_plural
属性现在会回退到InlineModelAdmin.verbose_name
+'s'
。jQuery 从版本 3.5.1 升级到 3.6.0 。
django.contrib.admindocs
¶
admindocs 现在允许复杂的设置,其中
ROOT_URLCONF
不是一个字符串。admindocs
的模型部分现在显示缓存的属性。
django.contrib.auth
¶
PBKDF2 密码哈希器的默认迭代次数从 260 , 000 增加到 320 , 000 。
新的
LoginView.next_page
属性和get_default_redirect_url()
方法允许自定义登录后的重定向。
django.contrib.gis
¶
新增对 SpatiaLite 5 的支持。
GDALRaster
现在允许在任何 GDAL 虚拟文件系统中创建栅格数据。新的
GISModelAdmin
类允许自定义用于GeometryField
的小部件,这是鼓励使用的,而不是不推荐使用的GeoModelAdmin
和OSMGeoAdmin
。
django.contrib.postgres
¶
PostgreSQL 后端现在支持通过服务名称进行连接。更多详情请参阅 PostgreSQL 连接配置。
新的
AddConstraintNotValid
操作允许在 PostgreSQL 上创建检查约束,而无需验证所有现有行是否满足新约束。新的
ValidateConstraint
操作允许验证在 PostgreSQL 上使用AddConstraintNotValid
创建的检查约束。新的
ArraySubquery()
表达式允许在 PostgreSQL 上使用子查询来构建值列表。新的
trigram_word_similar
查找以及TrigramWordDistance()
和TrigramWordSimilarity()
表达式允许使用 trigram 单词相似度。
django.contrib.staticfiles
¶
ManifestStaticFilesStorage
现在会将 JavaScript 源映射引用的路径替换为它们的哈希版本。ManifestFilesMixin
和ManifestStaticFilesStorage
的新参数manifest_storage
允许自定义清单文件的存储。
缓存¶
django.core.cache.backends.base.BaseCache
的新异步 API 开始了使缓存后端支持异步的过程。新的异步方法都有a
前缀的名称,例如aadd()
、aget()
、aset()
、aget_or_set()
或adelete_many()
。今后,
a
前缀将用于一般方法的异步变体。
CSRF¶
CSRF 保护现在会查看是否存在
Origin
标头。为了实现这一点,需要对CSRF_TRUSTED_ORIGINS
设置进行 一些更改。
表单¶
ModelChoiceField
现在会在引发invalid_choice
错误消息的ValidationError
中的params
参数中包含提供的值,这允许自定义错误消息使用%(value)s
占位符。BaseFormSet
现在会在渲染非表单错误时添加一个额外的类nonform
,以帮助区分它们与特定于表单的错误。BaseFormSet
现在允许通过设置deletion_widget
属性或覆盖get_deletion_widget()
方法来自定义在通过can_delete
删除表单时使用的小部件。
国际化¶
添加了对马来语的支持和翻译。
通用视图¶
DeleteView
现在使用FormMixin
,允许你提供一个Form
的子类,例如带有复选框的表单,来确认删除。此外,这还允许DeleteView
与django.contrib.messages.views.SuccessMessageMixin
配合使用。根据
FormMixin
,对于 POST 请求的对象删除是在form_valid()
中处理的。如果需要,应将delete()
处理程序中的自定义删除逻辑移动到form_valid()
或共享的辅助方法中。
日志¶
现在,用于 SQL 调用的数据库的别名会作为额外的上下文与每条消息一起传递到 django.db.backends 记录器中。
管理命令¶
runserver
管理命令现在支持--skip-checks
选项。在 PostgreSQL 上,
dbshell
现在支持指定密码文件。shell
命令现在在启动时会尊重sys.__interactivehook__
。这允许在交互式会话之间加载 shell 历史记录。因此,在 隔离 模式下运行时不再加载readline
。新的
BaseCommand.suppressed_base_arguments
属性允许在帮助输出中抑制不支持的默认命令选项。新的
startapp --exclude
和startproject --exclude
选项允许从模板中排除目录。
模型¶
新的
QuerySet.contains(obj)
方法返回查询集是否包含给定对象。它尝试以最简单和最快的方式执行查询。Round()
数据库函数的新precision
参数允许指定舍入后的小数位数。使用 SQLite 3.35+ 时,
QuerySet.bulk_create()
现在会为对象设置主键。DurationField
现在在 SQLite 上支持乘法和除法以及标量值。QuerySet.bulk_update()
现在会返回更新的对象数量。新的
Expression.empty_result_set_value
属性允许在函数用于空结果集时指定要返回的值。在 MariaDB 10.6+ 上,现在允许使用
QuerySet.select_for_update()
的skip_locked
参数。Lookup
表达式现在可以在QuerySet
的注释、聚合和直接筛选中使用。内置聚合函数的新 default 参数允许指定当查询集(或分组)不包含条目时要返回的值,而不是返回
None
。
请求和响应¶
SecurityMiddleware
现在会添加具有值'same-origin'
的 Cross-Origin Opener Policy 头,以防止跨源弹出窗口共享相同的浏览上下文。你可以通过将SECURE_CROSS_ORIGIN_OPENER_POLICY
设置为None
来阻止添加此头部。
信号¶
pre_migrate()
和post_migrate()
信号现在有一个新的stdout
参数,允许将输出重定向到类似流的对象。在发出详细输出时,应优先考虑使用它,以便在测试时能够正确捕获输出,而不是使用sys.stdout
和print()
。
模板¶
模板过滤器
floatformat
现在允许使用u
后缀来强制禁用本地化。
测试¶
django.test.utils.setup_databases()
的新参数serialized_aliases
决定了哪些DATABASES
别名的测试数据库应该被序列化以允许使用 serialized_rollback 特性。The
test --buffer
option now supports parallel tests.DiscoverRunner
的新参数logger
允许使用 Python logger 进行日志记录。新的
DiscoverRunner.log()
方法提供了一种记录消息的方式,它使用DiscoverRunner.logger
进行日志记录,如果未设置则打印到控制台。DiscoverRunner
can now execute tests in a random order using thetest --shuffle
option.test --parallel
选项现在支持值auto
,以为每个处理器核心运行一个测试进程。TestCase.captureOnCommitCallbacks()
现在会捕获在执行transaction.on_commit()
回调期间添加的新回调。
4.0 版本中不向后兼容的变更¶
数据库后端 API¶
本节介绍了第三方数据库后端可能需要的更改。
DatabaseOperations.year_lookup_bounds_for_date_field()
和year_lookup_bounds_for_datetime_field()
方法现在接受可选的iso_year
参数,以支持 ISO-8601 周编号年份的范围。DatabaseSchemaEditor._unique_sql()
和_create_unique_sql()
方法的第二个参数现在是fields
,而不再是columns
。
django.contrib.gis
¶
移除了对 PostGIS 2.3 的支持。
移除了对 GDAL 2.0 和 GEOS 3.5 的支持。
停止支持 PostgreSQL 9.6¶
PostgreSQL 9.6 的上游支持将在 2021 年 11 月结束。 Django 4.0 支持 PostgreSQL 10 及更高版本。
此外,psycopg2
的最低支持版本已从 2.5.4 提高到 2.8.4,因为 psycopg2
2.8.4 是第一个支持 Python 3.8 的版本。
停止支持 Oracle 12.2 和 18c¶
Oracle 12.2 的上游支持将于 2022 年 3 月结束,Oracle 18c 的上游支持将于 2021 年 6 月结束。 Django 3.2 将得到支持直至 2024 年 4 月。 Django 4.0 正式支持 Oracle 19c 。
CSRF_TRUSTED_ORIGINS
变更¶
格式变更¶
在 CSRF_TRUSTED_ORIGINS
设置中,值必须包括方案(例如,'http://'
或 'https://'
),而不仅仅是主机名。
此外,以点开头的值现在必须在点之前加上一个星号。例如,将 '.example.com'
更改为 'https://*.example.com'
。
系统检查会检测到任何所需的更改。
现在可能需要配置它¶
由于 CSRF 保护现在参考 Origin
标头,如果你通过将 CSRF_COOKIE_DOMAIN
(或者如果启用了 CSRF_USE_SESSIONS
,则为 SESSION_COOKIE_DOMAIN
)设置为以点开头的值以允许来自子域的请求,你可能需要设置 CSRF_TRUSTED_ORIGINS
。
SecurityMiddleware
不再设置 X-XSS-Protection
头¶
如果 SECURE_BROWSER_XSS_FILTER
设置为 True
,则 SecurityMiddleware
不再设置 X-XSS-Protection
头。此设置已被移除。
大多数现代浏览器不再支持 X-XSS-Protection
HTTP 头。你可以使用 Content-Security-Policy 来代替,但请不要允许 'unsafe-inline'
脚本。
如果您想要支持旧版浏览器并设置标头,请在自定义中间件中使用以下代码行:
response.headers.setdefault("X-XSS-Protection", "1; mode=block")
迁移自动检测器的更改¶
迁移自动检测器现在使用模型状态而不是模型类。此外,对于 ForeignKey
和 ManyToManyField
字段的迁移操作不再指定未在字段初始化期间传递的属性。
作为副作用,在某些情况下,运行 makemigrations
可能会为 ManyToManyField
和 ForeignKey
字段生成无操作的 AlterField
操作。
DeleteView
变更¶
DeleteView
现在使用 FormMixin
来处理 POST 请求。因此,任何在 delete()
处理程序中的自定义删除逻辑应该移动到 form_valid()
,或者如果需要的话,可以移动到共享的辅助方法。
Oracle 上的表和列命名方案发生了变化。¶
Django 4.0 无意中更改了 Oracle 上的表和列命名方案。这会导致模型和字段的名称超过 30 个字符的错误。不幸的是,需要重命名一些 Oracle 表和列。请使用 33789 中的升级脚本生成 RENAME
语句来更改命名方案。
杂项¶
已移除对
cx_Oracle
版本低于 7.0 的支持。为了允许在子路径上提供 Django 站点而不更改
STATIC_URL
的值,现在在默认的startproject
模板中从该设置中移除了前导斜杠(现在是'static/'
)。当直接访问
AdminSite
的管理index
视图时,不再使用never_cache
进行装饰,而是建议通过AdminSite.urls
属性或AdminSite.get_urls()
方法访问。对切片的查询集执行不支持的操作现在会引发
TypeError
而不是AssertionError
。未记录的
django.test.runner.reorder_suite()
函数已更名为reorder_tests()
。现在它接受一个测试的可迭代对象而不是测试套件,并返回一个测试的迭代器。现在,如果使用空的
name
调用FileSystemStorage.delete()
,会引发ValueError
而不是AssertionError
。如果使用无效的
content
或mimetype
参数调用EmailMultiAlternatives.attach_alternative()
或EmailMessage.attach()
,现在会引发ValueError
而不是AssertionError
。assertHTMLEqual()
不再将没有值的非布尔属性视为与具有相同名称和值的属性相等。现在,无法加载的测试,例如由于语法错误等原因,使用
test --tag
时始终匹配。未记录的
django.contrib.admin.utils.lookup_needs_distinct()
函数已更名为lookup_spawns_duplicates()
。未记录的
HttpRequest.get_raw_uri()
方法已被移除。HttpRequest.build_absolute_uri()
方法可能是一个合适的替代方法。未记录的
ModelAdmin.log_addition()
、log_change()
和log_deletion()
方法的object
参数已更名为obj
。NodeList.render()
不再将单个节点的render()
方法的输出转换为字符串。根据文档,Node.render()
应始终返回一个字符串。django.db.models.sql.query.Query
的where_class
属性以及ForeignObject
和ForeignObjectRel
的私有方法get_extra_restriction()
的where_class
参数已被移除。如果需要,可以初始化django.db.models.sql.where.WhereNode
。未记录的
Query.add_filter()
方法的filter_clause
参数被替换为两个位置参数filter_lhs
和filter_rhs
。CsrfViewMiddleware
现在使用request.META['CSRF_COOKIE_NEEDS_UPDATE']
代替request.META['CSRF_COOKIE_USED']
、request.csrf_cookie_needs_reset
和response.csrf_cookie_set
来跟踪 CSRF cookie 是否应该发送。这是一个未记录的私有 API。未记录的
TRANSLATOR_COMMENT_MARK
常量已从django.template.base
移动到django.utils.translation.template
。未记录的
django.db.migrations.state.ProjectState.__init__()
方法的real_apps
参数现在必须是一个集合(set),如果提供的话。RadioSelect
和CheckboxSelectMultiple
小部件现在在<div>
标签中呈现,以便屏幕阅读器更简洁地宣读它们。如果需要以前的行为,请使用来自 Django 3.2 的适当模板 覆盖小部件模板。模板过滤器
floatformat
不再依赖于USE_L10N
设置,并始终返回本地化的输出。使用u
后缀来禁用本地化。USE_L10N
设置的默认值已更改为True
。有关更多详细信息,请参阅上面的 本地化部分。作为 迁移到 zoneinfo 的一部分,
django.utils.timezone.utc
被更改为别名datetime.timezone.utc
。asgiref
的最低支持版本已从 3.3.2 增加到 3.4.1。
在 4.0 版本中废弃的功能¶
使用 pytz
时区¶
作为 迁移到 zoneinfo 的一部分,不推荐使用 pytz
时区。
相应地,以下函数的 is_dst
参数也已被弃用:
在 Django 5.0 中将移除对 pytz
的支持。
时区支持¶
为了遵循良好的实践,USE_TZ
设置的默认值将从 False
更改为 True
,并且在 Django 5.0 中将默认启用时区支持。
请注意,由 django-admin startproject
创建的默认 settings.py
文件自 Django 1.4 起就包括 USE_TZ = True
。
你可以在那之前在项目设置中将 USE_TZ
设置为 False
以选择不使用时区支持。
本地化¶
为了遵循良好的实践,USE_L10N
设置的默认值从 False
更改为 True
。
此外,从此版本开始,USE_L10N
已被弃用。从 Django 5.0 开始,默认情况下,Django 显示的任何日期或数字都将进行本地化。
Django 仍将支持 {% localize %}
标签以及 localize
/ unlocalize
过滤器。
杂项¶
SERIALIZE
测试设置已被弃用,因为可以从启用 serialized_rollback 选项的databases
推断出。未记录的
django.utils.baseconv
模块已被弃用。未记录的
django.utils.datetime_safe
模块已被弃用。在 Django 5.0 中,构建在请求上下文之外的站点地图的默认协议将从
'http'
更改为'https'
。DiscoverRunner.build_suite()
和DiscoverRunner.run_tests()
的extra_tests
参数已被弃用。在 Django 5.0 中,当没有行时,
ArrayAgg
、JSONBAgg
和StringAgg
聚合将返回None
,而不是分别返回[]
、[]
和''
。如果需要以前的行为,请显式将default
设置为Value([])
、Value('[]')
或Value('')
。django.contrib.gis.admin.GeoModelAdmin
和OSMGeoAdmin
类已被弃用。请改为使用ModelAdmin
和GISModelAdmin
。由于表单渲染现在使用模板引擎,未记录的
BaseForm._html_output()
辅助方法已被弃用。从
ErrorList
和ErrorDict
返回str
的能力已被弃用。预期这些方法返回一个SafeString
。
在 4.0 版本中移除的功能¶
这些功能已经完成了废弃周期,并在 Django 4.0 中被移除。
请参阅 在 3.0 中被废弃的功能 以获取有关这些更改的详细信息,包括如何删除对这些功能的使用。
django.utils.http.urlquote()
,urlquote_plus()
,urlunquote()
, 和urlunquote_plus()
已被移除。django.utils.encoding.force_text()
和smart_text()
已被移除。django.utils.translation.ugettext()
,ugettext_lazy()
,ugettext_noop()
,ungettext()
, 和ungettext_lazy()
已被移除。django.views.i18n.set_language()
不会在request.session
中设置用户语言(键为_language
)。alias=None
在django.db.models.Expression.get_group_by_cols()
子类的签名中是必需的。django.utils.text.unescape_entities()
已被移除。django.utils.http.is_safe_url()
已被移除。
请参阅 在 3.1 中被废弃的功能 以获取有关这些更改的详细信息,包括如何删除对这些功能的使用。
PASSWORD_RESET_TIMEOUT_DAYS
设置已被移除。isnull
查询不再允许使用非布尔值作为右侧的值。django.db.models.query_utils.InvalidQuery
异常类已被移除。django-admin.py
入口点已被移除。HttpRequest.is_ajax()
方法已被移除。已移除对由
django.contrib.messages.storage.cookie.CookieStorage
使用的 Django 3.1 之前版本的 cookie 值编码格式的支持。移除了对使用 SHA-1 哈希算法的 Django 3.1 之前版本密码重置令牌在管理站点的支持。
移除了对使用 Django 3.1 之前编码格式的会话的支持。
已移除对 Django 3.1 之前版本中使用 SHA-1 算法编码的
django.core.signing.Signer
签名的支持。已移除在
django.core.signing.loads()
中对 Django 3.1 之前版本中使用 SHA-1 算法编码的django.core.signing.dumps()
签名的支持。移除了对使用 SHA-1 算法的 Django 3.1 之前用户会话的支持。
django.utils.deprecation.MiddlewareMixin.__init__()
的get_response
参数是必需的,并且不接受None
。django.dispatch.Signal
的providing_args
参数已被移除。django.utils.crypto.get_random_string()
的length
参数是必需的。ModelMultipleChoiceField
的list
消息已被移除。不再支持将原始列别名传递给
QuerySet.order_by()
。NullBooleanField
模型字段已被移除,除了在历史迁移中的支持。django.conf.urls.url()
已被移除。django.contrib.postgres.fields.JSONField
模型字段已被移除,除了在历史迁移中的支持。django.contrib.postgres.fields.jsonb.KeyTransform
和django.contrib.postgres.fields.jsonb.KeyTextTransform
已被移除。django.contrib.postgres.forms.JSONField
已被移除。{% ifequal %}
和{% ifnotequal %}
模板标签已被移除。DEFAULT_HASHING_ALGORITHM
过渡设置已被移除。