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 的表达式,而不需要首先注释然后对注释进行过滤。

模型字段选择的枚举类型

现在可以使用自定义枚举类型 TextChoicesIntegerChoicesChoices 来定义 Field.choicesTextChoicesIntegerChoices 类型用于文本和整数字段。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

django.contrib.gis

django.contrib.postgres

django.contrib.sessions

django.contrib.syndication

缓存

文件存储

表单

国际化

日志

  • AdminEmailHandler 的新参数 reporter_class 允许提供一个 django.views.debug.ExceptionReporter 的子类,以自定义在 DEBUGFalse 时发送给站点 ADMINS 的异常回溯文本。

管理命令

模型

  • 添加了哈希数据库函数 MD5SHA1SHA224SHA256SHA384SHA512

  • 添加了 Sign 数据库函数。

  • Trunc 数据库函数的新参数 is_dst 决定了不存在和模糊的日期时间的处理方式。

  • connection.queries 现在在 PostgreSQL 上显示 COPY … TO 语句。

  • FilePathField 现在接受可调用对象作为 path

  • 允许自引用 ManyToManyField 的对称中间表。

  • CheckConstraintUniqueConstraintIndexname 属性现在支持使用 '%(app_label)s''%(class)s' 占位符进行应用标签和类插值。

  • 新的 Field.descriptor_class 属性允许模型字段通过重写它们的 描述符 来自定义获取和设置行为。

  • AvgSum 现在支持 distinct 参数。

  • 添加了 SmallAutoField,它的行为类似于 AutoField,但它只允许在某个(与数据库相关的)限制内的值。在Django支持的所有数据库中,值从 132767 都是安全的。

  • AutoFieldBigAutoFieldSmallAutoField 现在分别继承自 IntegerFieldBigIntegerFieldSmallIntegerField。系统检查和验证器现在也会正确继承。

  • FileField.upload_to 现在支持 pathlib.Path

  • 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() 方法。有关示例,请参阅 子类化内置数据库后端

请求和响应

安全

测试

  • 新的测试 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() 根据行是否存在执行了 INSERTUPDATE

这使得在提供默认主键值的情况下调用 Model.save() 等效于将 force_insert=True 传递给模型的 save()。尝试使用新的 Model 实例更新现有行将导致 IntegrityError

要更新特定主键值的现有模型,请使用 update_or_create() 方法或 QuerySet.filter(pk=…).update(…)。例如:

  1. >>> MyModel.objects.update_or_create(pk=existing_pk, defaults={"name": "new name"})
  2. >>> 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_insertcan_return_ids_from_bulk_insert 已更名为 can_return_columns_from_insertcan_return_rows_from_bulk_insert
  • 数据库函数现在在使用 datetime.timedelta 实例创建时处理 datetime.timezone 格式(例如 timezone(timedelta(hours=5)),这将输出 'UTC+05:00')。第三方后端应在准备 DateTimeFielddatetime_cast_date_sql()datetime_extract_sql() 等时处理这种格式。
  • 为了支持这些字段类型上的整数范围验证器,已经将 AutoFieldBigAutoFieldSmallAutoField 的条目添加到 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 项目在默认情况下更加安全,一些安全设置现在具有更安全的默认值:

有关这些更改的更多详细信息,请参阅上面的 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 翻译为单数短语,将所有其他数值视为复数。这对某些语言可能不正确。
  • 给模型的 ForeignKeyOneToOneField'_id' 属性分配一个值现在会取消对应字段的设置。之后访问该字段将导致查询。
  • patch_vary_headers() 现在按照 RFC 7231#section-7.1.4 处理星号 '*',即如果标头字段名称列表包含星号,则 Vary 标头将包含单个星号 '*'
  • 在 MySQL 8.0.16+ 上,PositiveIntegerFieldPositiveSmallIntegerField 现在包括一个检查约束,以防止数据库中出现负值。
  • 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() 已被移除。
  • staticfilesadmin_static 模板标签库已被移除。
  • django.contrib.staticfiles.templatetags.staticfiles.static() 已被移除。