Django 3.0 版本发行说明
2019 年 12 月 2 日
欢迎使用 Django 3.0 !
这些发行说明涵盖了 新功能,以及一些 不兼容的变化,当您从 Django 2.2 或更早版本升级时需要注意。我们已经 删除了一些已经完成了其弃用周期的功能,并且我们已经 开始了一些功能的弃用过程。
如果你要更新现有的项目,请看 如何将 Django 更新至新的版本 指南。
Python 兼容性
Django 3.0 支持 Python 3.6、3.7、3.8 和 3.9(截至 3.0.11 版)。我们 强烈推荐 并且只官方支持每个系列的最新版本。
Django 2.2.x 系列是最后一个支持 Python 3.5 的版本。
对于较旧版本的 Django 的第三方库支持
在发布 Django 3.0 后,我们建议第三方应用程序作者停止支持 Django 2.2 之前的所有版本。在那个时候,您应该能够使用 python -Wd
运行您包的测试,以便看到弃用警告。在进行弃用警告修复后,您的应用程序应该与 Django 3.0 兼容。
Django 3.0 新特性
MariaDB 支持
Django 现在正式支持 MariaDB 10.1 及更高版本。更多详情请参阅 MariaDB 注意事项。
ASGI 支持
Django 3.0 开始了我们使 Django 完全支持异步的旅程,通过提供作为 ASGI 应用程序运行的支持。
这是在我们现有的 WSGI 支持之外的补充。 Django 计划在可预见的未来同时支持两者。然而,异步功能只适用于在 ASGI 下运行的应用程序。
在当前阶段,异步支持仅适用于外部 ASGI 应用程序。内部的所有内容仍然是同步的。异步中间件、视图等尚不受支持。但是,您可以在 Django 应用程序周围使用 ASGI 中间件,从而可以将 Django 与其他 ASGI 框架结合使用。
除非您想开始尝试异步代码,否则没有必要切换您的应用程序,但如果您想了解更多信息,我们有关于使用 ASGI 部署的 文档。
请注意,由于这个改变的副作用,Django 现在可以识别异步事件循环,并会阻止您从异步上下文中调用标记为 “async unsafe” 的代码,比如 ORM 操作。如果您以前从异步代码中使用 Django,那么如果使用不正确,这可能会触发问题。如果看到 SynchronousOnlyOperation
错误,请仔细检查您的代码,并将任何数据库操作移动到同步的子线程中。
PostgreSQL 上的排除约束
新的 ExclusionConstraint 类允许在 PostgreSQL 上添加排除约束。约束通过在模型中使用 Meta.constraints 选项来添加。
过滤表达式
现在可以直接在 QuerySet
过滤器中使用输出 BooleanField 的表达式,而不需要首先注释然后对注释进行过滤。
模型字段选择的枚举类型
现在可以使用自定义枚举类型 TextChoices
、IntegerChoices
和 Choices
来定义 Field.choices。TextChoices
和 IntegerChoices
类型用于文本和整数字段。Choices
类允许为其他具体数据类型定义兼容的枚举。这些自定义枚举类型支持可翻译的人类可读标签,并可以通过枚举或其成员的属性来访问。有关更多详细信息和示例,请参阅 枚举类型。
次要特性
django.contrib.admin
- 在 ModelAdmin.list_display 中的属性上添加了对
admin_order_field
属性的支持。 - 新的 ModelAdmin.get_inlines() 方法允许根据请求或模型实例来指定内联。
- Select2 库的版本已从 4.0.3 升级到 4.0.7 。
- jQuery 的版本已从 3.3.1 升级到 3.4.1 。
django.contrib.auth
- 在 PasswordResetConfirmView 中新增了
reset_url_token
属性,允许指定作为密码重置 URL 组件显示的令牌参数。 - 添加了 BaseBackend 类,以便更容易自定义身份验证后端。
- 添加了 get_user_permissions() 方法,以对应现有的 get_group_permissions() 方法。
- 在 django.contrib.auth.forms 中的用户名、电子邮件和密码字段的小部件中添加了 HTML
autocomplete
属性,以更好地与浏览器密码管理器交互。 - createsuperuser 现在在非交互模式下,当没有提供相应的命令行参数时,会回退到环境变量来获取密码和必填字段。
- REQUIRED_FIELDS 现在支持 ManyToManyField。
- 新的 UserManager.with_perm() 方法返回具有指定权限的用户。
- PBKDF2 密码哈希器的默认迭代次数从 150 , 000 增加到 180 , 000 。
django.contrib.gis
- 允许 MySQL 空间查询函数在真实几何对象上操作。之前的支持仅限于边界框。
- 添加了 GeometryDistance 函数,在 PostGIS 上支持。
- 在 Distance 中添加了对
furlong
单位的支持。 - GEOIP_PATH 设置现在支持 pathlib.Path。
- GeoIP2 类现在接受 pathlib.Path 的
path
。
django.contrib.postgres
- 新的 RangeOperators 有助于避免在可以与 RangeField 一起使用的 SQL 运算符中出现拼写错误。
- 新的 RangeBoundary 表达式表示范围的边界。
- 新的 AddIndexConcurrently 和 RemoveIndexConcurrently 类允许在 PostgreSQL 上使用
CONCURRENTLY
创建和删除索引。
django.contrib.sessions
- 新的 get_session_cookie_age() 方法允许动态指定会话 cookie 的过期时间。
django.contrib.syndication
- 在 django.contrib.syndication.views.Feed 中添加了
language
类属性,以自定义 feed 的语言。默认值是 get_language(),而不是 LANGUAGE_CODE。
缓存
- add_never_cache_headers() 和 never_cache() 现在在
Cache-Control
头中添加了private
指令。
文件存储
- 新的 Storage.get_alternative_name() 方法允许自定义生成文件名的算法,如果已经存在具有上传名称的文件。
表单
- 通过设置 ordering_widget 属性或覆盖 get_ordering_widget(),表单集合可以控制在通过 can_order 排序表单时使用的小部件。
国际化
- 添加了 LANGUAGE_COOKIE_HTTPONLY、LANGUAGE_COOKIE_SAMESITE 和 LANGUAGE_COOKIE_SECURE 设置,用于在语言 cookie 上设置
HttpOnly
、SameSite
和Secure
标志。这些设置的默认值保留了以前的行为。 - 增加了对乌兹别克语的支持和翻译。
日志
- AdminEmailHandler 的新参数
reporter_class
允许提供一个django.views.debug.ExceptionReporter
的子类,以自定义在 DEBUG 为False
时发送给站点 ADMINS 的异常回溯文本。
管理命令
- 新的 compilemessages —ignore 选项允许在搜索要编译的
.po
文件时忽略特定目录。 - showmigrations —list 在
--verbosity
为 2 及以上时现在会显示已应用的日期时间。 - 在 PostgreSQL 上,dbshell 现在支持客户端端的 TLS 证书。
- inspectdb 现在在外键具有唯一或主键约束时会检查 OneToOneField。
- 新的 --skip-checks 选项在运行命令之前跳过运行系统检查。
- startapp —template 和 startproject —template 选项现在支持存储在 XZ 存档(
.tar.xz
、.txz
)和 LZMA 存档(.tar.lzma
、.tlz
)中的模板。
模型
添加了 Sign 数据库函数。
Trunc 数据库函数的新参数
is_dst
决定了不存在和模糊的日期时间的处理方式。connection.queries
现在在 PostgreSQL 上显示COPY … TO
语句。FilePathField 现在接受可调用对象作为
path
。允许自引用 ManyToManyField 的对称中间表。
CheckConstraint、UniqueConstraint 和 Index 的
name
属性现在支持使用'%(app_label)s'
和'%(class)s'
占位符进行应用标签和类插值。新的 Field.descriptor_class 属性允许模型字段通过重写它们的 描述符 来自定义获取和设置行为。
添加了 SmallAutoField,它的行为类似于 AutoField,但它只允许在某个(与数据库相关的)限制内的值。在Django支持的所有数据库中,值从
1
到32767
都是安全的。AutoField、BigAutoField 和 SmallAutoField 现在分别继承自
IntegerField
、BigIntegerField
和SmallIntegerField
。系统检查和验证器现在也会正确继承。CheckConstraint 现在在 MySQL 8.0.16+ 上受支持。
django.db.backends.base.BaseDatabaseFeatures
的新方法allows_group_by_selected_pks_on_model()
允许优化GROUP BY
子句,只需要选定的模型主键。默认情况下,它仅在 PostgreSQL 上支持托管的模型。要启用针对未托管模型的
GROUP BY
主键优化,您需要子类化 PostgreSQL 数据库引擎,并根据需要覆盖 features 类的allows_group_by_selected_pks_on_model()
方法。有关示例,请参阅 子类化内置数据库后端。
请求和响应
- 允许使用 memoryview 内容初始化 HttpResponse。
- 例如,在 Django 模板中,现在允许使用下划线(例如,
user_agent
)来查找 HttpRequest.headers,而不是连字符。
安全
- X_FRAME_OPTIONS 现在默认为
'DENY'
。在较旧的版本中,X_FRAME_OPTIONS 设置默认为'SAMEORIGIN'
。如果您的站点使用自身的框架,您将需要显式设置X_FRAME_OPTIONS = 'SAMEORIGIN'
,以便它们继续正常工作。 - SECURE_CONTENT_TYPE_NOSNIFF 现在默认为
True
。启用此选项后,SecurityMiddleware 会在所有尚未设置该标头的响应上设置 X-Content-Type-Options: nosniff 标头。 - SecurityMiddleware 现在可以发送 Referrer-Policy 标头。
测试
- 新的测试 Client 参数
raise_request_exception
允许控制请求期间引发的异常是否也应该在测试中引发。默认情况下,该值为True
,以保持向后兼容性。如果它为False
并且发生异常,测试客户端将返回一个带有属性 exc_info 的 500 响应,该属性是一个元组,提供了发生的异常信息。 - 可以使用新的 test -k 选项通过测试名称模式选择要运行的测试和测试用例。
- HTML 比较,如 assertHTMLEqual() 所使用的,现在将相同字符引用的文本、字符引用和实体引用视为等效。
- Django 测试运行程序现在支持在支持的浏览器上的无头模式的 Selenium 测试。添加
--headless
选项以启用此模式。 - Django 测试运行程序现在支持
--start-at
和--start-after
选项,以从特定顶级模块开始运行测试。 - Django 测试运行程序现在支持
--pdb
选项,以在每次出现错误或失败时启动调试器。
3.0 版本中的不向后兼容的更改。
在提供主键默认值时,使用 Model.save()
Model.save() 在保存新的 Model
实例并提供主键的默认值时不再尝试查找行,而总是执行单个 INSERT
查询。在较早的 Django 版本中,Model.save()
根据行是否存在执行了 INSERT
或 UPDATE
。
这使得在提供默认主键值的情况下调用 Model.save()
等效于将 force_insert=True 传递给模型的 save()
。尝试使用新的 Model
实例更新现有行将导致 IntegrityError
。
要更新特定主键值的现有模型,请使用 update_or_create() 方法或 QuerySet.filter(pk=…).update(…)
。例如:
>>> MyModel.objects.update_or_create(pk=existing_pk, defaults={"name": "new name"})
>>> MyModel.objects.filter(pk=existing_pk).update(name="new name")
数据库后端 API
本节介绍了第三方数据库后端可能需要的更改。
DatabaseIntrospection.get_geometry_type()
的第二个参数现在是行描述而不是列名。DatabaseIntrospection.get_field_type()
可能不再返回元组。- 如果数据库可以在添加字段的同一 SQL 语句中创建外键,请添加适当的 SQL 到
SchemaEditor.sql_create_column_inline_fk
;否则,请设置DatabaseFeatures.can_create_inline_fk = False
。 DatabaseFeatures.can_return_id_from_insert
和can_return_ids_from_bulk_insert
已更名为can_return_columns_from_insert
和can_return_rows_from_bulk_insert
。- 数据库函数现在在使用 datetime.timedelta 实例创建时处理 datetime.timezone 格式(例如
timezone(timedelta(hours=5))
,这将输出'UTC+05:00'
)。第三方后端应在准备 DateTimeField 的datetime_cast_date_sql()
、datetime_extract_sql()
等时处理这种格式。 - 为了支持这些字段类型上的整数范围验证器,已经将
AutoField
、BigAutoField
和SmallAutoField
的条目添加到DatabaseOperations.integer_field_ranges
中。第三方后端可能需要自定义默认条目。 DatabaseOperations.fetch_returned_insert_id()
已被替换为fetch_returned_insert_columns()
,它返回由INSERT … RETURNING
语句返回的值列表,而不是单个值。DatabaseOperations.return_insert_id()
已被替换为return_insert_columns()
,它接受一个fields
参数,该参数是要在插入后返回的字段的可迭代对象。通常这只是自动生成的主键。
django.contrib.admin
- 管理者模型历史更改消息现在更偏向于使用可读性更高的字段标签,而不是字段名称。
django.contrib.gis
- 不再支持 PostGIS 2.1 。
- 不再支持 SpatiaLite 4.1 和 4.2 。
- 不再支持 GDAL 1.11 和 GEOS 3.4 。
不再支持 PostgreSQL 9.4 。
上游对于 PostgreSQL 9.4 的支持在 2019 年 12 月结束。 Django 3.0 支持 PostgreSQL 9.5 及更高版本。
不再支持 Oracle 12.1 。
Oracle 12.1 的上游支持将于 2021 年 7 月结束。 Django 2.2 将支持至 2022 年 4 月。 Django 3.0 正式支持 Oracle 12.2 和 18c 版本。
移除了私有的 Python 2 兼容 API 。
尽管在 Django 2.0 中移除了对 Python 2 的支持,但某些私有 API 未被移除,以便第三方应用程序在 Python 2 生命周期结束之前仍可继续使用它们。
由于我们预计在添加对 Django 3.0 的支持时,应用程序将放弃对 Python 2 的兼容性,因此我们此时正在移除这些 API 。
django.test.utils.str_prefix()
- 在 Python 3 中,字符串不再具有 ‘u’ 前缀。django.test.utils.patch_logger()
- 请改用 unittest.TestCase.assertLogs()。django.utils.lru_cache.lru_cache()
- 是 functools.lru_cache() 的别名。django.utils.decorators.available_attrs()
- 此函数返回functools.WRAPPER_ASSIGNMENTS
。django.utils.decorators.ContextDecorator
- 是 contextlib.ContextDecorator 的别名。django.utils._os.abspathu()
- 是 os.path.abspath() 的别名。django.utils._os.upath()
和npath()
- 在 Python 3 上不执行任何操作。django.utils.six
- 移除对此库的使用或切换到 six。django.utils.encoding.python_2_unicode_compatible()
- 是six.python_2_unicode_compatible()
的别名。django.utils.functional.curry()
- 请使用 functools.partial() 或 functools.partialmethod。请参阅 5b1c389603a353625ae1603ba345147356336afb。django.utils.safestring.SafeBytes
- 自 Django 2.0 起未使用。
FILE_UPLOAD_PERMISSIONS
设置的新默认值。
在较早的版本中,FILE_UPLOAD_PERMISSIONS 设置的默认值为 None
。在默认的:setting:FILE_UPLOAD_HANDLERS 的情况下,这导致上传的文件根据其大小和使用的上传处理程序而具有不同的权限。
现在,默认情况下,FILE_UPLOAD_PERMISSIONS
默认为 0o644
,以避免这种不一致性。
安全设置的新默认值。
为了使 Django 项目在默认情况下更加安全,一些安全设置现在具有更安全的默认值:
- X_FRAME_OPTIONS 现在默认为
'DENY'
。 - SECURE_CONTENT_TYPE_NOSNIFF 现在默认为
True
。
有关这些更改的更多详细信息,请参阅上面的 What’s New Security section。
杂项
ContentType.__str__()
现在包括模型的app_label
以消除在不同应用程序中具有相同名称的模型的歧义。- 由于已弃用在 cookie 中而不是会话中访问语言,因此
LocaleMiddleware
不再在会话中查找用户的语言,而 django.contrib.auth.logout() 在注销后不再保留会话的语言。 - django.utils.html.escape() 现在使用 html.escape() 来转义 HTML。这会将
'
转换为'
,而不是以前的等效十进制代码'
。 django-admin test -k
选项现在与 unittest -k 选项一样工作,而不再作为--keepdb
的快捷方式。- 对于
pywatchman
版本低于 1.2.0 的支持已被移除。 - 在
doseq=False
时,urlencode() 现在会像标准库的 urllib.parse.urlencode() 函数一样,将可迭代的值按原样编码,而不是迭代它们。 intword
模板过滤器现在将1.0
翻译为单数短语,将所有其他数值视为复数。这对某些语言可能不正确。- 给模型的 ForeignKey 或 OneToOneField 的
'_id'
属性分配一个值现在会取消对应字段的设置。之后访问该字段将导致查询。 - patch_vary_headers() 现在按照 RFC 7231#section-7.1.4 处理星号
'*'
,即如果标头字段名称列表包含星号,则Vary
标头将包含单个星号'*'
。 - 在 MySQL 8.0.16+ 上,
PositiveIntegerField
和PositiveSmallIntegerField
现在包括一个检查约束,以防止数据库中出现负值。 alias=None
已添加到 Expression.get_group_by_cols() 的签名中。RegexPattern
,由 re_path() 使用,不再返回带有None
值的关键字参数,以便传递给视图,用于缺少的可选命名组。
在 3.0 中被废弃的功能
django.utils.encoding.force_text()
和 smart_text()
smart_text()
和 force_text()
别名(自 Django 2.0 起)的 smart_str()
和 force_str()
已被弃用。如果您的代码支持 Python 2,请忽略此弃用,因为在 Python 2 中,smart_str()
和 force_str()
的行为是不同的。
杂项
django.utils.http.urlquote()
,urlquote_plus()
,urlunquote()
, 和urlunquote_plus()
已被弃用,建议使用它们的别名函数:urllib.parse.quote(), quote_plus(), unquote(), 和 unquote_plus()。django.utils.translation.ugettext()
,ugettext_lazy()
,ugettext_noop()
,ungettext()
, 和ungettext_lazy()
已被弃用,建议使用它们的别名函数:django.utils.translation.gettext(), gettext_lazy(), gettext_noop(), ngettext(), 和 ngettext_lazy()。- 为了限制会话的创建,从而支持某些缓存策略,在 Django 4.0 中,django.views.i18n.set_language() 将停止在会话中设置用户的语言。自 Django 2.1 起,语言始终存储在 LANGUAGE_COOKIE_NAME cookie 中。
django.utils.text.unescape_entities()
已被弃用,建议使用 html.unescape()。请注意,与unescape_entities()
不同,html.unescape()
立即评估延迟字符串。- 为了避免对有效范围的可能混淆,私有的内部实用程序
is_safe_url()
被重命名为url_has_allowed_host_and_scheme()
。通常情况下,一个 URL 具有允许的主机和方案并不意味着它是”安全的”。例如,它可能仍然被引用不正确。请确保在不受信任的 URL 的路径组件上也使用 iri_to_uri()。
在 3.0 版本中删除的功能。
这些功能已经完成了其弃用周期,并在 Django 3.0 中被移除。
有关这些更改的详细信息,包括如何移除对这些功能的使用,请参阅 在 2.0 中被废弃的功能。
django.db.backends.postgresql_psycopg2
模块已被移除。django.shortcuts.render_to_response()
已被移除。DEFAULT_CONTENT_TYPE
设置已被移除。HttpRequest.xreadlines()
已被移除。Field.from_db_value()
和Expression.convert_value()
的context
参数支持已被移除。QuerySet.earliest()
和latest()
的field_name
关键参数已被移除。
请参阅 在 2.1 中被废弃的功能 以获取有关这些更改的详细信息,包括如何移除对这些功能的使用。
ForceRHR
GIS 函数已被移除。django.utils.http.cookie_date()
已被移除。staticfiles
和admin_static
模板标签库已被移除。django.contrib.staticfiles.templatetags.staticfiles.static()
已被移除。