2020 年 8 月 4 日
欢迎来到 Django 3.1 版本!
此版本说明涵盖了一些 新特性 ,以及从 Django 3.0 或更早版本升级时需要注意的 向后不兼容 的地方。我们已经 删除了一些过期的功能 ,并且已经开始 淘汰一些特性 。
如果你要更新现有的项目,请看 How to upgrade Django to a newer version 指南。
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 配置
The new DEFAULT_HASHING_ALGORITHM transitional setting allows specifying
the default hashing algorithm to use for encoding cookies, password reset
tokens in the admin site, user sessions, and signatures created by
django.core.signing.Signer and django.core.signing.dumps().
Support for SHA-256 was added in Django 3.1. If you are upgrading multiple
instances of the same project to Django 3.1, you should set
DEFAULT_HASHING_ALGORITHM to 'sha1' during the transition, in order to
allow compatibility with the older versions of Django. Note that this requires
Django 3.1.1+. Once the transition to 3.1 is complete you can stop overriding
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。
缓存
- 根据 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选项允许向数据库的命令行客户端传递额外的参数。 flush和sqlflush命令现在包括 SQL 来重置 SQLite 上的序列。
模型
- 新的
ExtractIsoWeekDay函数从DateField和DateTimeField中提取 ISO-8601 周天,新的iso_week_day查询可以按 ISO-8601 周天查询。 QuerySet.explain()现在支持:- MySQL 8.0.16+ 上的
TREE格式, - MySQL 8.0.18+ 和 MariaDB 上的
analyze选项。
- MySQL 8.0.16+ 上的
- 添加了
PositiveBigIntegerField,它的作用很像PositiveIntegerField,只是它只允许在一定(依赖于数据库的)限制下取值。从0到9223372036854775807的值在 Django 支持的所有数据库中都是安全的。 - 新的
RESTRICT选项为ForeignKey`和OneToOneField的on_delete参数模拟了 SQL 约束ON DELETE RESTRICT的行为。 CheckConstraint.check现在支持布尔表达式。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()方法根据AcceptHTTP 头返回请求是否接受给定的 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测试数据库配置允许在创建测试数据库时禁止迁移。 - Django 测试运行器现在支持
test --buffer选项,以丢弃通过测试的输出。 DiscoverRunner现在会跳过对非 测试所引用 的数据库进行系统检查。TransactionTestCase关闭现在在 MySQL 上的速度更快了,这是因为flush命令的改进。作为一个副作用,后者不会再在关闭时自动重置序列。如果你的测试需要这个功能,请启用TransactionTestCase.reset_sequences。
URLs
- Path 转换器 现在可以在
to_url()中引发ValueError,在反查 URL 时表示不匹配。
实用程序
filepath_to_uri()现在支持pathlib.Path。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。
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 响应背后的逻辑现在是基于AcceptHTTP 头而不是X-Requested-WithHTTP 头的存在。 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小部件不再使用requiredHTML 属性进行渲染。 - 删除了未记录的
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。- Media 类现在不使用
type属性来渲染<script>标签,以遵循 WHATWG 建议 。 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()方法,如果你的代码依赖于客户端AcceptHTTP 头。如果你正在编写自己的 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)。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的支持。
讨论区