Django 3.1 版本发行说明¶
2020 年 8 月 4 日
欢迎来到 Django 3.1 版本!
此版本说明涵盖了一些 新特性 ,以及从 Django 3.0 或更早版本升级时需要注意的 向后不兼容 的地方。我们已经 删除了一些过期的功能 ,并且已经开始 淘汰一些特性 。
如果你要更新现有的项目,请看 如何将 Django 更新至新的版本 指南。
Python 兼容性¶
Django 3.1 支持 Python 3.6、3.7、3.8 和 3.9(从 3.1.3 开始)。我们 强烈推荐 且官方只支持每个系列的最新版本。
Django 3.1 新特性¶
异步视图和中间件支持¶
Django 现在支持完全异步的请求路径,包括:
要开始使用异步视图,你需要使用 async def
来声明一个视图:
async def my_view(request):
await asyncio.sleep(0.5)
return HttpResponse("Hello, async world!")
无论你是在 WSGI 或 ASGI 模式下运行,都支持所有的异步功能。但是,在 WSGI 模式下使用 async 代码会有性能上的惩罚。你可以在 异步支持 文档中阅读更多的具体内容。
你可以自由地混合异步和同步视图、中间件和测试,只要你愿意。Django 会确保你最终使用正确的执行上下文。我们希望大多数项目会保持大部分视图的同步,只有少数视图在异步模式下运行,但这完全是你的选择。
Django 的 ORM、缓存层和其他做长期网络调用的代码还不支持异步访问。我们希望在即将发布的版本中增加对它们的支持。但是,异步视图是很理想的,如果你在视图里面做了大量的 API 或 HTTP 调用,你现在可以原生地将所有这些 HTTP 调用并行进行,以大大加快你的视图的执行速度。
异步支持应该是完全向后兼容的,我们已经尝试确保它不会对你现有的同步代码造成速度上的倒退。它应该不会对任何现有的 Django 项目产生明显的影响。
JSONField 适用于所有支持的数据库后端。¶
Django 现在包含 models.JSONField
和 forms.JSONField
,可以在所有支持的数据库后端使用。这两个字段都支持使用自定义 JSON 编码器和解码器。模型字段支持自省、查找和变换,这些功能以前只有 PostgreSQL 才有:
from django.db import models
class ContactInfo(models.Model):
data = models.JSONField()
ContactInfo.objects.create(
data={
"name": "John",
"cities": ["London", "Cambridge"],
"pets": {"dogs": ["Rufus", "Meg"]},
}
)
ContactInfo.objects.filter(
data__name="John",
data__pets__has_key="dogs",
data__cities__contains="London",
).delete()
如果你的项目使用了 django.contrib.postgres.fields.JSONField
,加上相关的表单字段和变换,你应该调整使用新的字段,并生成和应用数据库迁移。目前,旧的字段和变换体作为新字段的引用留存下来,并且 从这个版本开始取消。
DEFAULT_HASHING_ALGORITHM
配置¶
新的 DEFAULT_HASHING_ALGORITHM
过渡设置允许指定用于编码 cookie、管理员站点中的密码重置令牌、用户会话以及由 django.core.signing.Signer
和 django.core.signing.dumps()
创建的签名的默认哈希算法。
在 Django 3.1 中添加了对 SHA-256 的支持。如果您正在将同一项目的多个实例升级到 Django 3.1,您应该在过渡期间将 DEFAULT_HASHING_ALGORITHM
设置为 'sha1'
,以便与旧版本的 Django 兼容。请注意,这需要 Django 3.1.1+。一旦完成到 3.1 的过渡,您可以停止覆盖 DEFAULT_HASHING_ALGORITHM
。
因为在 Django 4.0 中,对使用 SHA-1 算法的令牌、cookie、会话和签名的支持将被取消,所以这个配置从这个版本开始就被取消了。
次要特性¶
django.contrib.admin
¶
新的
django.contrib.admin.EmptyFieldListFilter
为ModelAdmin.list_filter
允许在管理的变更列表视图中过滤空值(空字符串和空值)。管理员更改列表视图右侧的过滤器现在包含一个清除所有过滤器的链接。
管理员现在在大屏幕上有一个侧栏,以便于导航。它是默认启用的,但可以通过使用一个自定义的
AdminSite
和设置AdminSite.enable_nav_sidebar
为False
来禁用。渲染侧边栏需要访问当前请求,以便设置 CSS 和 ARIA 角色的负担。这就需要使用
OPTIONS
的'context_processors'
选项中的'django.template.context_processors.request'
。最初的空
extra
内联现在可以被删除,与动态创建的内联相同。XRegExp
从 2.0.0 版本升级到 3.2.0。jQuery 从 3.4.1 版本升级到 3.5.1。
Select2 库从 4.0.7 版本升级到 4.0.13。
django.contrib.auth
¶
PBKDF2 密码哈希的默认迭代次数从 180,000 增加到 216,000。
新的
PASSWORD_RESET_TIMEOUT
配置允许定义密码重置链接的有效秒数。我们鼓励这样做,而不是使用被废弃的PASSWORD_RESET_TIMEOUT_DAYS
配置,后者将在 Django 4.0 中被删除。密码重置机制现在使用 SHA-256 散列算法。在 Django 4.0 之前,对使用旧的散列算法的令牌的支持仍然存在。
AbstractBaseUser.get_session_auth_hash()
现在使用 SHA-256 散列算法。在 Django 4.0 之前,对使用旧的散列算法的用户会话的支持仍然存在。
django.contrib.contenttypes
¶
新的
remove_stale_contenttypes --include-stale-apps
选项允许从以前安装的应用程序中删除陈旧的内容类型,这些应用程序已经从INSTALLED_APPS
中删除。
django.contrib.gis
¶
relate
查找现已在 MariaDB 上支持。添加了
LinearRing.is_counterclockwise
属性。AsGeoJSON
现已在 Oracle 上支持。添加了
AsWKB
和AsWKT
函数。增加了对 PostGIS 3 和 GDAL 3 的支持。
django.contrib.humanize
¶
intword
模板过滤器现在支持负整数。
django.contrib.postgres
¶
新的
BloomIndex
类允许在数据库中创建bloom
索引。新的BloomExtension
迁移操作安装bloom
扩展来增加对该索引的支持。get_FOO_display()
现在支持ArrayField
和RangeField
。新的
rangefield.lower_inc
,rangefield.lower_inf
、rangefield.upper_inc
和rangefield.upper_inf
查找允许通过绑定类型查询RangeField
。rangefield.contained_by
现在支持SmallAutoField
、AutoField
、BigAutoField
、SmallIntegerField
和DecimalField
。SearchQuery
现在支持 PostgreSQL 11+ 上的'websearch'
搜索类型。SearchQuery.value
现在支持查询表达式。新的
SearchHeadline
类可以高亮显示搜索结果。search
查找现在支持查询表达式。新的
SearchRank
的cover_density
参数允许按覆盖密度进行排名。SearchRank
的新normalization
参数允许进行排名规范化。新的
ExclusionConstraint.deferrable
属性允许创建可推迟的排除约束。
django.contrib.sessions
¶
SESSION_COOKIE_SAMESITE
配置现在允许'None'
(字符串)值明确表示所有同站和跨站请求都会发送 cookie。
django.contrib.staticfiles
¶
STATICFILES_DIRS
配置现在支持pathlib.Path
。
缓存¶
根据 RFC 7234#section-5.2.2.2,
cache_control()
装饰器和patch_cache_control()
方法现在支持Cache-Control
头的no-cache
指令中的多个字段名。delete()
现在在成功删除键时返回True
,否则返回False
。
CSRF¶
CSRF_COOKIE_SAMESITE
配置现在允许'None'
(字符串)值来明确说明所有同站和跨站请求都会发送 cookie。
电子邮件¶
附件邮件后端 使用的
EMAIL_FILE_PATH
配置,现在支持pathlib.Path
。
错误报告¶
django.view.debug.SafeExceptionReporterFilter
现在可以过滤异常报告中request.META
中的敏感值。新的
SafeExceptionReporterFilter.cleansed_substitute
和SafeExceptionReporterFilter.hidden_settings
属性允许在异常报告中自定义敏感配置和request.META
过滤。在应用配置过滤时,技术 404 调试视图现在尊重
DEFAULT_EXCEPTION_REPORTER_FILTER
。新的
DEFAULT_EXCEPTION_REPORTER
允许提供django.views.debug.ExceptionReporter
子类来定制异常报告的生成。详情请参见 自定义错误报告。
文件存储¶
FileSystemStorage.save()
方法现在支持pathlib.Path
。FileField
和ImageField
现在可以接受storage
的调用。这允许你在运行时修改所使用的存储,例如为不同的环境选择不同的存储。
表单¶
ModelChoiceIterator
,被ModelChoiceField
和ModelMultipleChoiceField
使用,现在使用ModelChoiceIteratorValue
,可以被部件用来访问模型实例。详情请看 迭代关系选择。django.forms.DateTimeField
现在接受 ISO 8601 日期时间格式的子集,包括可选的时区,例如2019-10-10T06:47
、2019-10-10T06:47:23+04:00
或2019-10-10T06:47:23Z
。如果提供了时区,将始终保留时区,即使USE_TZ
为False
时,也会返回时区感知的日期时间。此外,
DateTimeField
现在在将字段输入转换为datetime
值时,除了使用DATETIME_INPUT_FORMATS
外,还使用DATE_INPUT_FORMATS
。MultiWidget.widgets
现在接受一个字典,允许自定义子部件name
属性。新的
BoundField.widget_type
属性可用于根据部件类型动态调整表单渲染。
国际化¶
LANGUAGE_COOKIE_SAMESITE
配置现在允许'None'
(字符串)值明确表示所有同站和跨站请求都会发送 cookie。增加了对阿尔及利亚阿拉伯语、伊博语、吉尔吉斯语、塔吉克语和土库曼语的支持和翻译。
管理命令¶
新的
check --database
选项允许指定数据库别名,以便运行database
系统检查。以前,通过向命令传递database
标签,为所有设置的DATABASES
启用这些检查。新的
migrate --check
选项使命令在检测到未应用的迁移时以非零状态退出。CommandError
的新returncode
参数允许自定义管理命令的退出状态。新的
dbshell -- ARGUMENTS
选项允许向数据库的命令行客户端传递额外的参数。
模型¶
新的
ExtractIsoWeekDay
函数从DateField
和DateTimeField
中提取 ISO-8601 周天,新的iso_week_day
查询可以按 ISO-8601 周天查询。QuerySet.explain()
现在支持:MySQL 8.0.16+ 上的
TREE
格式,MySQL 8.0.18+ 和 MariaDB 上的
analyze
选项。
添加了
PositiveBigIntegerField
,它的作用很像PositiveIntegerField
,只是它只允许在一定(依赖于数据库的)限制下取值。从0
到9223372036854775807
的值在 Django 支持的所有数据库中都是安全的。新的
RESTRICT
选项为ForeignKey
和OneToOneField
的on_delete
参数模拟了 SQL 约束ON DELETE RESTRICT
的行为。CheckConstraint.check
now supports boolean expressions.RelatedManager.add()
、create()
和set()
方法现在接受可调用对象参数作为through_defaults
参数的值。QuerySet.datetimes()
的新is_dst
参数决定了如何处理不存在和不明确的日期。新的
F
表达式bitxor()
方法允许 bitwise XOR 操作。QuerySet.bulk_create()
在使用 MariaDB 10.5+ 时,现在可以设置对象的主键。DatabaseOperations.sql_flush()
方法现在可以在 MySQL 上生成更有效的 SQL,对于不需要重置序列的表,使用DELETE
而不是TRUNCATE
语句。SQLite 函数现已在 Python 3.8+ 上被标记为
deterministic
。这允许在检查约束和部分索引中使用它们。新的
UniqueConstraint.deferrable
属性允许创建可推迟的唯一约束。
分页¶
Paginator
现在可以迭代产生其页面。
请求和响应¶
如果
ALLOWED_HOSTS
为空且DEBUG=True
,则在Host
头中允许使用 localhost 的子域,例如static.localhost
。HttpResponse.set_cookie()
和HttpResponse.set_signed_cookie()
现在允许使用samesite='None'
(字符串)来明确说明所有同站和跨站请求都会发送cookie。新的
HttpRequest.accepts()
方法根据Accept
HTTP 头返回请求是否接受给定的 MIME 类型。
安全¶
SECURE_REFERRER_POLICY
配置现在默认为'same-origin'
。设置了这个之后,SecurityMiddleware
会在所有还没有设置 Referrer 政策 头的情况下,将其设置为same-origin
。这可以防止Referer
头被发送到其他来源。如果你需要以前的行为,明确地设置SECURE_REFERRER_POLICY
为None
。django.core.signing.Signer
、django.core.signing.load()
和django.core.signing.dumps()
的默认算法改为 SHA-256。在 Django 4.0 之前,仍然支持用旧的 SHA-1 算法进行签名。另外,
Signer
的新algorithm
参数允许自定义哈希算法。
模板¶
重新命名的
translate
和blocktranslate
模板标签被引入,用于模板代码的国际化。旧的trans
和blocktrans
模板标签的别名继续工作,并将在可预见的未来保留。include
模板标签现在接受模板名称的可迭代对象。
测试¶
SimpleTestCase
现在实现了debug()
方法,允许在不收集结果和捕获异常的情况下运行测试。这可以用来支持在调试器下运行测试。新的
MIGRATE
测试数据库配置允许在创建测试数据库时禁止迁移。DiscoverRunner
can now discard output for passing tests using thetest --buffer
option.DiscoverRunner
现在会跳过对非 测试所引用 的数据库进行系统检查。TransactionTestCase
关闭现在在 MySQL 上的速度更快了,这是因为flush
命令的改进。作为一个副作用,后者不会再在关闭时自动重置序列。如果你的测试需要这个功能,请启用TransactionTestCase.reset_sequences
。
URLs¶
Path 转换器 现在可以在
to_url()
中引发ValueError
,在反查 URL 时表示不匹配。
实用程序¶
parse_duration()
现在支持 ISO 8601 格式的小数点用逗号分隔。parse_datetime()
、parse_duration()
和parse_time()
现在支持用逗号分隔毫秒。
杂项¶
SQLite 后端现在支持
pathlib.Path
为NAME
的配置。由
startproject
命令生成的settings.py
现在使用pathlib.Path
代替os.path
来建立文件系统路径。现在允许在支持时区的数据库上进行
TIME_ZONE
设置。
3.1 中的不向后兼容的变更¶
数据库后端 API¶
本节介绍了第三方数据库后端可能需要的更改。
DatabaseOperations.fetch_returned_insert_columns()
现在需要一个额外的returning_params
参数。connection.timezone
属性现在默认为'UTC
,或者当USE_TZ
为True
时,支持时区的数据库上的TIME_ZONE
。此前,在支持时区的数据库上是None
。connection._nodb_connection
属性改为connection._nodb_cursor()
方法,现在返回一个产生游标的上下文管理器,并在退出with
语句后自动关闭游标和连接。DatabaseClient.runshell()
现在需要一个额外的parameters
参数,作为传递给命令行客户端的额外参数列表。DatabaseOperations.sql_flush()
的sequences
位置参数被只用关键字的布尔参数reset_sequences
取代。如果True
,截断表的序列将被重置。DatabaseOperations.sql_flush()
的allow_cascade
参数现在是一个纯关键字的参数。DatabaseOperations.execute_sql_flush()
的using
位置参数被删除。该方法现在使用被调用实例的数据库。第三方数据库后端必须实现对
JSONField
的支持,或者将DatabaseFeatures.supports_json_field
设置为False
。如果不支持存储基元,则设置DatabaseFeatures.supports_primitives_in_json_field
为False
。如果 JSON 的数据类型为真,则设置DatabaseFeatures.has_native_json_field
为True
。如果不支持jsonfield.contains
和jsonfield.contains_by
,则将DatabaseFeatures.support_json_field_contains
设置为False
。第三方数据库后端必须实现对
JSONField
的自省,或者将can_introspect_json_field
设置为False
。
丢弃了对 MariaDB 10.1 的支持¶
对 MariaDB 10.1 的上游支持在 2020 年 10 月结束。Django 3.1 支持 MariaDB 10.2 及以上版本。
contrib.admin
浏览器支持¶
管理不再支持传统的 Internet Explorer 浏览器。关于支持的浏览器,请参见 管理常见问题。
AbstractUser.first_name
的 max_length
增加到 150¶
包含了 django.contrib.auth.models.User.first_name
的迁移。如果你有一个继承自 AbstractUser
的自定义用户模型,你将需要为你的用户模型生成并应用数据库迁移。
如果你想保留 first name 的 30 个字符限制,请使用自定义表单:
from django import forms
from django.contrib.auth.forms import UserChangeForm
class MyUserChangeForm(UserChangeForm):
first_name = forms.CharField(max_length=30, required=False)
如果你想在管理中编辑用户时保留这个限制,请将 UserAdmin.form
设置为使用这个表单:
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
class MyUserAdmin(UserAdmin):
form = MyUserChangeForm
admin.site.unregister(User)
admin.site.register(User, MyUserAdmin)
杂项¶
cache
使用的缓存密钥和make_template_fragment_key()
生成的缓存密钥与旧版本 Django 生成的密钥不同。升级到 Django 3.1 后,第一次请求任何之前缓存的模板片段都会被缓存错过。从
set_language()
视图中返回重定向回退或 204 HTTP 响应背后的逻辑现在是基于Accept
HTTP 头而不是X-Requested-With
HTTP 头的存在。django.db.models.query
、django.db.models.sql
和django.db.models.sql.datastructures
中的django.core.exceptions.EmptyResultSet
的兼容性导入被移除。删除了
django.db.models.field
中django.core.exceptions.FieldDoesNotExist
的兼容性导入。删除了
django.forms.utils.pretty_name()
和django.forms.boundfield.BoundField
的兼容性导入。django.template.base
中的Context
、ContextPopException
和RequestContext
的兼容性导入被移除。删除了
django.contrib.admin.helpers.ACTION_CHECKBOX_NAME
中的兼容性导入。设置为相对路径的
STATIC_URL
和MEDIA_URL
配置现在以服务器提供的SCRIPT_NAME
的值为前缀(如果没有设置,则为/
)。这一变化不应影响设置为有效 URL 或绝对路径的配置。ConditionalGetMiddleware
不再为空content
的响应添加ETag
头。django.utils.disturators.classproperty()
装饰器被公开并移到django.utils.functional.classproperty()
。floatform
模板过滤器现在对四舍五入为零的负数输出(正)``0```。Meta.ordering
和Meta.unique_together <django.db.models.Options.unique_together>`
模块中模型的选项,以前是元组,现在是列表。管理日历部件现在根据开放组规范处理两位数的年份,即 69 和 99 之间的值被映射到上一个世纪,0 和 68 之间的值被映射到当前世纪。
从
DATETIME_INPUT_FORMATS
的默认列表中删除了仅限日期的格式。当初始数据存在时,
FileInput
小部件不再使用required
HTML 属性进行渲染。删除了未记录的
django.views.debug.ExceptionReporterFilter
类。根据 自定义错误报告 文档,与DEFAULT_EXCEPTION_REPORTER_FILTER
一起使用的类需要继承django.views.debug.SafeExceptionReporterFilter
。cache_page()
装饰器设置的缓存超时现在优先于Cache-Control
头的max-age
指令。在
ForeignKey.to_field
参数中提供一个非本地的远程字段,现在会引发FieldError
。SECURE_REFERRER_POLICY
现在默认为'same-origin'
。更多细节请参见 新变化 安全章节。check
管理命令现在只对使用check --database
选项指定的数据库别名运行database
系统检查。migrate
管理命令现在只运行database
系统检查要迁移的数据库。管理 CSS 类
row1
和row2
被删除,取而代之的是:nth-child(odd)
和:nth-child(even)
伪类。make_password()
函数现在要求其参数为字符串或字节。其他类型的参数应该显式地转换为其中之一。删除了
AsKML
函数中未记录的version
参数。JSON 和 YAML 序列化器,由
dumpdata
使用,现在默认使用 Unicode 转储所有数据。如果你需要以前的行为,传递ensure_ascii=True
给 JSON 序列化器,或者allow_unicode=False
给 YAML 序列化器。自动重新加载器不再监控内置 Django 翻译文件的变化。
mysqlclient
的最低支持版本从 1.3.13 增加到 1.4.0。未记录的
django.contrib.postgres.forms.InvalidJSONInput
和django.contrib.postgres.forms.JSONString
被移至django.forms.field
。删除了未记录的
django.contrib.postgres.field.jsonb.JsonAdapter
类。{% localize off %}
标签和unlocalize
过滤器不再遵守DECIMAL_SEPARATOR
配置。asgiref
的最低支持版本从 3.2 增加到 3.2.10。ModelChoiceIterator
,由ModelChoiceField
和ModelMultipleChoiceField
使用,现在产生 2 个包含ModelChoiceIteratorValue
实例的选择,作为每个选择的第一个value
元素。在大多数情况下,这个代理是透明的,但如果你需要field
值本身,请使用ModelChoiceIteratorValue.value
属性代替。
在 3.1 中被废弃的功能¶
PostgreSQL 的 JSONField
¶
django.contrib.postgres.field.JSONField
和 django.contrib.postgres.forms.JSONField
被废弃,改用 models.JSONField
和 forms.JSONField
。
未记录的 django.contrib.postgres.fields.jsonb.KeyTransform
和 django.contrib.postgres.fields.jsonb.KeyTextTransform
也被弃用,改用 django.db.models.fields.json
中的变换。
新的 JSONField
、KeyTransform
和 KeyTextTransform
可用于所有支持的数据库后端。
杂项¶
PASSWORD_RESET_TIMEOUT_DAYS
配置已被取消,改为PASSWORD_RESET_TIMEOUT
。未记录的
isnull
查找使用非布尔值作为右侧的用法已被废弃,请使用True
或False
代替。勉强记录的
django.db.models.query_utils.InvalidQuery
异常类被废弃,取而代之的是FieldDoesNotExist
和FieldError
。django-admin.py
的入口点已被废弃,改为django-admin
。HttpRequest.is_ajax()
方法已被废弃,因为它依赖于 jQuery 特定的方式来表示 AJAX 调用,而当前的用法倾向于使用 JavaScript Fetch API 。根据你的用例,你可以写你自己的 AJAX 检测方法,或者使用新的HttpRequest.accepts()
方法,如果你的代码依赖于客户端Accept
HTTP 头。如果你正在编写自己的 AJAX 检测方法,
request.is_ajax()
可以完全复制为request.headers.get('x-requested-with') == 'XMLHttpRequest'
。传递
None
作为django.utils.deprecation.MiddlewareMixin.__init__()
的第一个参数是过时的。CookieStorage
使用的 cookie 值的编码格式与旧版本 Django 生成的格式不同。在 Django 4.0 之前,仍然支持旧的格式。会话的编码格式与旧版 Django 生成的格式不同。在 Django 4.0 之前,仍然支持旧的格式。
Signal
的纯文档化providing_args
参数已被废弃。如果你依赖这个参数作为文档,你可以将文本移到代码注释或 docstring 中。没有
length
参数的情况下调用django.utils.crypto.get_random_string()
已被废弃。ModelMultipleChoiceField
的list
信息已被弃用,改为invalid_list
。向
QuerySet.order_by()
传递原始列别名已经被废弃。通过事先在RawSQL
中传递别名,可以达到同样的效果。NullBooleanField
模型字段已弃用,建议使用BooleanField(null=True, blank=True)
。django.conf.urls.url()
的django.urls.re_path()
别名已被废弃。{% ifequal %}
和{% ifnotequal %}
模板标签已被废弃,改为{% if %}
。{% if %}
涵盖了所有的用例,但如果你需要继续使用这些标签,可以将它们从 Django 中提取到一个模块中,并作为一个内置标签包含在'buildins'
选项中的OPTIONS
中。DEFAULT_HASHING_ALGORITHM
过渡性配置已废弃。
3.1 中删除的功能¶
这些功能已经到了废弃周期,在 Django 3.1 中被删除。
参见 在 2.2 中被废弃的功能,了解这些变化的细节,包括如何删除这些功能的使用。
django.utils.timezone.FixedOffset
被删除。django.core.paginator.QuerySetPaginator
被删除。一个模型的
Meta.ordering
不影响GROUP BY
的查询。django.contrib.postgres.fields.FloatRangeField
和django.contrib.postgres.forms.FloatRangeField
被删除。FILE_CHARSET
配置被删除。django.contrib.staticfiles.storage.CachedStaticFilesStorage
被删除。RemoteUserBackend.configure_user()
方法需要request
作为第一个位置参数。取消对
SimpleTestCase.allow_database_queries
和TransactionTestCase.multi_db
的支持。