Django 4.0发行说明

December 7, 2021

欢迎来到姜戈4.0!

这些发行说明涵盖 new features ,还有一些 backwards incompatible changes 在从Django 3.2或更早版本升级时,您需要注意这一点。我们已经 begun the deprecation process for some features

请参阅 如何将Django升级到更新版本 如果您要更新现有项目,请提供指南。

Python兼容性

Django 4.0支持Python3.8、3.9和3.10。我们 强烈推荐 并且仅官方支持每个系列的最新版本。

Django 3.2.x系列是最后一个支持Python3.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 是来自Python3.9的Python标准库的一部分。这个 backports.zoneinfo 如果您使用的是Python3.8,包将自动与Django一起安装。

迁移到 zoneinfo 应该在很大程度上透明。在表单和模板中选择当前时区、将DateTime实例转换为当前时区以及在UTC中对Aware DateTime执行的操作不受影响。

但是,如果您正在使用非UTC时区,并且使用 pytz normalize()localize() API,可能使用 TIME_ZONE 设置时,您将需要审核代码,因为 pytzzoneinfo 并不完全等同。

为了给这样的审计留出时间,过渡时期的 USE_DEPRECATED_PYTZ 设置允许继续使用 pytz 在4.x版本周期内。此设置将在Django 5.0中删除。

此外,a pytz_deprecation_shim 包,由 zoneinfo 作者,可用于帮助从 pytz 。此程序包提供垫片,以帮助您安全地删除 pytz ,并有详细的 migration guide 展示如何迁移到新的 zoneinfo API接口。

vbl.使用 pytz_deprecation_shim 以及 USE_DEPRECATED_PYTZ 如果您需要渐进式更新路径,建议使用过渡设置。

功能唯一约束

新的 *expressions 的位置论据 UniqueConstraint() 允许在表达式和数据库函数上创建函数唯一约束。例如::

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 password hasher 比PBKDF2更安全,推荐使用。然而,它不是默认的,因为它需要OpenSSL1.1+和更大的内存。

Redis缓存后端

新的 django.core.cache.backends.redis.RedisCache 缓存后端内置Redis缓存支持。 redis-py 需要3.0.0或更高版本。有关更多详细信息,请参阅 documentation on caching with Redis in Django

基于模板的表单呈现

FormsFormsets ,以及 ErrorList 现在使用模板引擎呈现,以增强定制。请看新的 render()get_context() ,以及 template_nameFormformset renderingFormset

次要特征

django.contrib.admin

django.contrib.admindocs

  • 管理员现在允许在以下情况下进行深奥的设置 ROOT_URLCONF 不是字符串。

  • 的模型部分 admindocs 现在显示缓存的属性。

django.contrib.auth

django.contrib.gis

  • 添加了对SpatiaLite 5的支持。

  • GDALRaster 现在允许在任何GDAL虚拟文件系统中创建栅格。

  • 新的 GISModelAdmin 类允许自定义用于 GeometryField 。这是鼓励而不是弃用的 GeoModelAdminOSMGeoAdmin

django.contrib.postgres

django.contrib.staticfiles

高速缓存

  • 新的异步API用于 django.core.cache.backends.base.BaseCache 开始使缓存后端与异步兼容的过程。新的异步方法都有 a 带有前缀的名称,例如 aadd()aget()aset()aget_or_set() ,或 adelete_many()

    展望未来, a 前缀通常用于方法的异步变体。

CSRF

表格

  • ModelChoiceField 现在将提供的值包括在 params 一种提升的参数 ValidationError 对于 invalid_choice 错误消息。这允许自定义错误消息使用 %(value)s 占位符。

  • BaseFormSet 现在使用附加的类呈现非表单错误。 nonform 以帮助将它们与特定于表单的错误区分开来。

  • BaseFormSet 现在允许自定义在通过以下方式删除表单时使用的小部件 can_delete 通过设置 deletion_widget 属性或重写 get_deletion_widget() 方法。

国际化

  • 添加了对马来语的支持和翻译。

通用视图

  • DeleteView 现在使用 FormMixin ,允许您提供一个 Form 子类,例如,带有复选框以确认删除。此外,这还允许 DeleteView 与…一起发挥作用 django.contrib.messages.views.SuccessMessageMixin

    根据 FormMixin 中处理POST请求的对象删除 form_valid() 。中的自定义删除逻辑 delete() 处理程序应移至 form_valid() ,或者根据需要共享帮助器方法。

日志记录

  • 现在,SQL调用中使用的数据库别名作为额外的上下文与每条消息一起传递给 django.db.backends 伐木者。

管理命令

型号

  • 新的 QuerySet.contains(obj) 方法返回查询集是否包含给定对象。这会尝试以最简单、最快的方式执行查询。

  • 新的 precision 的论据 Round() 数据库功能允许指定四舍五入后的小数位数。

  • QuerySet.bulk_create() 现在使用SQLite 3.35+时设置对象的主键。

  • DurationField 现在支持在SQLite上按标量值乘除。

  • QuerySet.bulk_update() 现在返回更新的对象数。

  • 新的 Expression.empty_result_set_value 属性允许指定在对空结果集使用函数时要返回的值。

  • 这个 skip_locked 的论点 QuerySet.select_for_update() 现在在MariaDB 10.6+上允许。

  • Lookup 现在可以在以下位置使用表达式 QuerySet 注释、聚合和直接在筛选器中。

  • 新的 default 内置聚合的参数允许在查询集(或分组)不包含条目时指定要返回的值,而不是 None

请求和响应

信号

模板

  • floatformat 模板筛选器现在允许使用 u 用于强制禁用本地化的后缀。

测试

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支持PostgreSQL10及更高版本。

此外,受支持的最低版本 psycopg2 从2.5.4增加到2.8.4,因为 psycopg2 2.8.4是第一个支持Python3.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_TRUSTED_ORIGINS ,特别是当您通过设置允许来自子域的请求时 CSRF_COOKIE_DOMAIN (或 SESSION_COOKIE_DOMAIN 如果 CSRF_USE_SESSIONS 已启用)设置为以点开头的值。

SecurityMiddleware 不再设置 X-XSS-Protection 标题

这个 SecurityMiddleware 不再设置 X-XSS-Protection 标头,如果 SECURE_BROWSER_XSS_FILTER 设置为 True 。该设置将被删除。

大多数现代浏览器不支持 X-XSS-Protection HTTP标头。您可以使用 Content-Security-Policy 不允许 'unsafe-inline' 而不是脚本。

如果您希望支持传统浏览器并设置标题,请在自定义中间件中使用此行::

response.headers.setdefault("X-XSS-Protection", "1; mode=block")

迁移自动检测更改

迁移自动检测器现在使用模型状态而不是模型类。此外,迁移操作 ForeignKeyManyToManyField 字段不再指定在初始化期间未传递给字段的属性。

作为一个副作用,跑步 makemigrations 可能会产生无操作 AlterField 针对以下方面的操作 ManyToManyFieldForeignKey 在某些情况下为字段。

DeleteView 变化

DeleteView 现在使用 FormMixin 来处理POST请求。因此,中的任何自定义删除逻辑 delete() 处理程序应移至 form_valid() ,或共享帮助器方法(如果需要)。

Oracle上的表和列命名方案更改

Django 4.0无意中更改了Oracle上的表和列命名方案。这会导致名称长度超过30个字符的模型和字段出错。遗憾的是,需要重命名一些Oracle表和列。使用中的升级脚本 33789 生成 RENAME 更改命名方案的语句。

杂项

  • 支持 cx_Oracle <7.0将被删除。

  • 允许对子路径上的Django站点提供服务而不更改 STATIC_URL ,则从该设置中删除前导斜杠(现在 'static/' )在默认情况下 startproject 模板。

  • 这个 AdminSite 适用于管理员的方法 index 视图不再用来装饰 never_cache 直接访问时,而不是通过建议的 AdminSite.urls 属性,或 AdminSite.get_urls() 方法。

  • 切片查询集上不受支持的操作现在引发 TypeError 而不是 AssertionError

  • 未登记的人 django.test.runner.reorder_suite() 函数已重命名为 reorder_tests() 。它现在接受可迭代的测试而不是测试套件,并返回测试的迭代器。

  • 叫唤 FileSystemStorage.delete() 带着一个空的 name 现在提高 ValueError 而不是 AssertionError

  • 叫唤 EmailMultiAlternatives.attach_alternative()EmailMessage.attach() 带有无效的 contentmimetype 现在引起了争论 ValueError 而不是 AssertionError

  • assertHTMLEqual() 不再将值不等于具有相同名称和值的属性的非布尔属性视为。

  • 无法加载的测试(例如,由于语法错误)现在在使用 test --tag

  • 未登记的人 django.contrib.admin.utils.lookup_needs_distinct() 函数已重命名为 lookup_spawns_duplicates()

  • 未登记的人 HttpRequest.get_raw_uri() 方法被移除。这个 HttpRequest.build_absolute_uri() 方法可能是一种合适的替代方法。

  • 这个 object 无证之辩 ModelAdmin.log_addition()log_change() ,以及 log_deletion() 方法被重命名为 obj

  • RssFeedAtom1Feed ,并且它们的子类现在将不包含任何内容的元素作为自结束标记发出。

  • NodeList.render() 不再强制转换 render() 方法将单个节点转换为字符串。 Node.render() 应始终返回记录在案的字符串。

  • 这个 where_class 的属性 django.db.models.sql.query.Query 以及 where_class 对列兵的争论 get_extra_restriction() 方法论 ForeignObjectForeignObjectRel 都被移除了。如果需要,初始化 django.db.models.sql.where.WhereNode 取而代之的是。

  • 这个 filter_clause 无证之辩 Query.add_filter() 方法被两个位置参数替换 filter_lhsfilter_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.basedjango.utils.translation.template

  • 这个 real_apps 无证之辩 django.db.migrations.state.ProjectState.__init__() 方法现在必须是一个集(如果提供)。

  • RadioSelectCheckboxSelectMultiple 现在,微件呈现在 <div> 标记,这样屏幕阅读器就可以更简洁地通知它们。如果您需要先前的行为, override the widget template 使用Django 3.2中的适当模板。

  • 这个 floatformat 模板筛选器不再依赖 USE_L10N 设置并始终返回本地化输出。使用 u 后缀以禁用本地化。

  • 的缺省值 USE_L10N 设置更改为 True 。请参阅 Localization section 有关更多详细信息,请参见上文。

  • 作为该计划的一部分 move to zoneinfodjango.utils.timezone.utc 更改为别名 datetime.timezone.utc

  • 支持的最低版本 asgiref 从3.3.2增加到3.4.1。

4.0中不推荐使用的功能

使用 pytz 时区

作为该计划的一部分 move to zoneinfo ,使用 pytz 时区已弃用。

因此, is_dst 也不建议使用以下参数:

支持使用 pytz 将在Django 5.0中删除。

时区支持

为了遵循良好做法, USE_TZ 设置将从 FalseTrue ,在Django 5.0中默认会启用时区支持。

请注意,默认设置为 settings.py 文件创建者 django-admin startproject 包括 USE_TZ = True 从Django 1.4开始。

您可以设置 USE_TZFalse 在此之前在您的项目设置中选择退出。

本土化

为了遵循良好做法, USE_L10N 设置更改自 FalseTrue

更有甚者 USE_L10N 自本版本起不再推荐使用。从Django 5.0开始,默认情况下,Django显示的任何日期或数字都将被本地化。

这个 {% localize %} 标记和 localize / unlocalize Django仍然会尊重Filters。

杂项

  • SERIALIZE 测试设置已弃用,因为它可以从 databasesserialized_rollback 选项已启用。

  • 未登记的人 django.utils.baseconv 模块已弃用。

  • 未登记的人 django.utils.datetime_safe 模块已弃用。

  • 在请求上下文之外构建的站点地图的默认站点地图协议将从 'http''https' 在Django 5.0中。

  • 这个 extra_tests 论据 DiscoverRunner.build_suite()DiscoverRunner.run_tests() 已弃用。

  • 这个 ArrayAggJSONBAgg ,以及 StringAgg 聚合将返回 None 当没有行而不是 [][] ,以及 '' 分别在Django 5.0中。如果需要前面的行为,请显式设置 defaultValue([])Value('[]') ,或 Value('')

  • 这个 django.contrib.gis.admin.GeoModelAdminOSMGeoAdmin 类已弃用。使用 ModelAdminGISModelAdmin 取而代之的是。

  • 由于表单呈现现在使用模板引擎,因此未记录的 BaseForm._html_output() 帮助器方法已弃用。

  • 能够返回一个 str 从… ErrorListErrorDict 已弃用。预计这些方法将返回 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() 方法被移除。

  • 支持使用的Cookie值的Django 3.1之前的编码格式 django.contrib.messages.storage.cookie.CookieStorage 被移除。

  • 删除了管理站点(使用SHA-1散列算法)中对Django 3.1之前的密码重置令牌的支持。

  • 删除了对Django 3.1之前的会话编码格式的支持。

  • 对Django 3.1之前版本的支持 django.core.signing.Signer 删除签名(用SHA-1算法编码)。

  • 对Django 3.1之前版本的支持 django.core.signing.dumps() 中的签名(使用SHA-1算法编码) django.core.signing.loads() 被移除。

  • 删除了对Django 3.1之前版本的用户会话(使用SHA-1算法)的支持。

  • 这个 get_response 论据 django.utils.deprecation.MiddlewareMixin.__init__() 是必需的,但不接受 None

  • 这个 providing_args 论证 django.dispatch.Signal 被移除。

  • 这个 length 论证 django.utils.crypto.get_random_string() 是必需的。

  • 这个 list 邮件地址为 ModelMultipleChoiceField 被移除。

  • 支持将原始列别名传递给 QuerySet.order_by() 被移除。

  • 这个 NullBooleanField 除历史迁移中的支持外,型号字段将被删除。

  • django.conf.urls.url() 被移除。

  • 这个 django.contrib.postgres.fields.JSONField 除历史迁移中的支持外,型号字段将被删除。

  • django.contrib.postgres.fields.jsonb.KeyTransformdjango.contrib.postgres.fields.jsonb.KeyTextTransform 都被移除了。

  • django.contrib.postgres.forms.JSONField 被移除。

  • 这个 {{% ifequal %}}{{% ifnotequal %}} 模板标记将被删除。

  • 这个 DEFAULT_HASHING_ALGORITHM 已删除过渡设置。