Django 5.0发行说明

December 4, 2023

欢迎来到Django 5.0!

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

见 如何将Django升级到更新版本 如果正在更新现有项目,则提供指南。

python兼容性

Django 5.0支持Python3.10、3.11和3.12。我们 highly recommend 并且仅官方支持每个系列的最新版本。

Django 4.2.x系列是最后一个支持Python3.8和3.9的版本。

第三方库支持旧版本的Django

随着Django 5.0的发布,我们建议第三方应用程序作者放弃对Django 4.2之前的所有版本的支持。那时,您应该能够使用以下命令运行包的测试 python -Wd 以便出现弃用警告。在进行了弃用警告修复后,您的应用程序应该与Django 5.0兼容。

Django 5.0中的新特性

管理中的面过滤器

现在,当通过用户界面切换时,将在管理更改列表中显示所应用的过滤器的面计数。此行为可以通过新的 ModelAdmin.show_facets 属性。有关详细信息,请参阅 小平面 。

用于表单域呈现的简化模板

Django 5.0引入了字段组和字段组模板的概念。这简化了Django表单域的相关元素的呈现,如标签、小部件、帮助文本和错误。

例如,下面的模板:

<form>
...
<div>
  {{ form.name.label_tag }}
  {% if form.name.help_text %}
    <div class="helptext" id="{{ form.name.auto_id }}_helptext">
      {{ form.name.help_text|safe }}
    </div>
  {% endif %}
  {{ form.name.errors }}
  {{ form.name }}
  <div class="row">
    <div class="col">
      {{ form.email.label_tag }}
      {% if form.email.help_text %}
        <div class="helptext" id="{{ form.email.auto_id }}_helptext">
          {{ form.email.help_text|safe }}
        </div>
      {% endif %}
      {{ form.email.errors }}
      {{ form.email }}
    </div>
    <div class="col">
      {{ form.password.label_tag }}
      {% if form.password.help_text %}
        <div class="helptext" id="{{ form.password.auto_id }}_helptext">
          {{ form.password.help_text|safe }}
        </div>
      {% endif %}
      {{ form.password.errors }}
      {{ form.password }}
    </div>
  </div>
</div>
...
</form>

现在可以简化为:

<form>
...
<div>
  {{ form.name.as_field_group }}
  <div class="row">
    <div class="col">{{ form.email.as_field_group }}</div>
    <div class="col">{{ form.password.as_field_group }}</div>
  </div>
</div>
...
</form>

as_field_group() 呈现字段时使用 "django/forms/field.html" 默认模板,并且可以基于每个项目、每个字段或每个请求进行自定义。看见 可重复使用的字段组模板 。

数据库计算的默认值

新的 Field.db_default 参数设置数据库计算的默认值。例如::

from django.db import models
from django.db.models.functions import Now, Pi


class MyModel(models.Model):
    age = models.IntegerField(db_default=18)
    created = models.DateTimeField(db_default=Now())
    circumference = models.FloatField(db_default=2 * Pi())

数据库生成的模型字段

新的 GeneratedField 允许创建数据库生成的列。此字段可在所有受支持的数据库后端上使用,以创建始终根据其他字段计算的字段。例如::

from django.db import models
from django.db.models import F


class Square(models.Model):
    side = models.IntegerField()
    area = models.GeneratedField(
        expression=F("side") * F("side"),
        output_field=models.BigIntegerField(),
        db_persist=True,
    )

用于声明字段选择的更多选项

Field.choices (for model fields) and ChoiceField.choices (for form fields) allow for more flexibility when declaring their values. In previous versions of Django, choices should either be a list of 2-tuples, or an 枚举类型 subclass, but the latter required accessing the .choices attribute to provide the values in the expected form:

from django.db import models

Medal = models.TextChoices("Medal", "GOLD SILVER BRONZE")

SPORT_CHOICES = [
    ("Martial Arts", [("judo", "Judo"), ("karate", "Karate")]),
    ("Racket", [("badminton", "Badminton"), ("tennis", "Tennis")]),
    ("unknown", "Unknown"),
]


class Winner(models.Model):
    name = models.CharField(...)
    medal = models.CharField(..., choices=Medal.choices)
    sport = models.CharField(..., choices=SPORT_CHOICES)

Django 5.0添加了对接受映射或Callable而不是Iterable的支持,也不再需要 .choices 直接用于扩展 enumeration types **

from django.db import models

Medal = models.TextChoices("Medal", "GOLD SILVER BRONZE")

SPORT_CHOICES = {  # Using a mapping instead of a list of 2-tuples.
    "Martial Arts": {"judo": "Judo", "karate": "Karate"},
    "Racket": {"badminton": "Badminton", "tennis": "Tennis"},
    "unknown": "Unknown",
}


def get_scores():
    return [(i, str(i)) for i in range(10)]


class Winner(models.Model):
    name = models.CharField(...)
    medal = models.CharField(..., choices=Medal)  # Using `.choices` not required.
    sport = models.CharField(..., choices=SPORT_CHOICES)
    score = models.IntegerField(choices=get_scores)  # A callable is allowed.

在引擎盖下提供的 choices 对象被规范化为规范形式的二元组列表。 choices 值即会更新。有关更多信息,请查看 model field reference on choices 。

次要特征

django.contrib.admin

  • 新的 AdminSite.get_log_entries() 方法允许为站点列出的日志条目自定义查询集。

  • 这个 django.contrib.admin.AllValuesFieldListFilter , ChoicesFieldListFilter , RelatedFieldListFilter ,以及 RelatedOnlyFieldListFilter 管理筛选器现在可以处理多值查询参数。

  • XRegExp 从3.2.0版升级到5.1.1版。

  • 新的 AdminSite.get_model_admin() 方法返回给定模型类的管理类。

  • 中的属性 ModelAdmin.list_display 现在支持 boolean 属性。

  • JQuery从3.6.4版升级到3.7.1版。

django.contrib.auth

django.contrib.contenttypes

django.contrib.gis

django.contrib.messages

django.contrib.postgres

异步视图

  • 在ASGI下, http.disconnect 现在可以处理事件了。这允许视图在客户端在生成响应之前断开连接时执行任何必要的清理。看见 处理断开连接 了解更多详细信息。

装饰者

错误报告

文件存储

  • File.open() 现在传递所有位置 (*args )和关键字参数 (**kwargs )添加到Python的内置 open() 。

形式

  • 新的 assume_scheme 论据 URLField 允许指定默认URL方案。

  • 为了提高可访问性,进行了以下更改:

    • 表单域现在包括 aria-describedby 使屏幕阅读器能够将表单域与其帮助文本相关联的HTML属性。

    • 无效的表单域现在包括 aria-invalid="true" Html属性。

国际化

  • 现已提供对维吾尔语的支持和翻译。

迁徙

模型

分页

信号

  • 新的 Signal.asend() 和 Signal.asend_robust() 方法允许异步信号调度。信号接收器可以是同步的或异步的,并且将自动适应正确的呼叫风格。

模板

  • 新的 escapeseq 模板筛选器适用 escape 序列中的每个元素。

测验

验证器

5.0中向后不兼容的更改

数据库后端API

本节描述第三方数据库后端可能需要的更改。

  • DatabaseFeatures.supports_expression_defaults 应设置为 False 如果数据库不支持使用数据库函数作为默认设置。

  • DatabaseFeatures.supports_default_keyword_in_insert 应设置为 False 如果数据库不支持 DEFAULT 输入关键字 INSERT 查询。

  • DatabaseFeatures.supports_default_keyword_in_bulk_insert 应设置为 False 如果数据库不支持 DEFAULT 批量输入的关键字 INSERT 查询。

django.contrib.gis

  • 删除了对GDAL 2.2和2.3的支持。

  • 删除了对GEOS 3.6和3.7的支持。

django.contrib.sitemaps

  • 这个 django.contrib.sitemaps.ping_google() 函数和 ping_google 管理命令将被删除,因为Google Sitemaps ping终结点已弃用,并将于2024年1月删除。

  • 这个 django.contrib.sitemaps.SitemapNotFound 异常类已删除。

已放弃对MySQL<8.0.11的支持

删除了对MySQL 8.0.x系列预发布的支持。Django 5.0支持MySQL 8.0.11及更高版本。

vbl.使用 create_defaults__exact 现在可能需要 QuerySet.update_or_create()

QuerySet.update_or_create() 现在支持参数 create_defaults 。因此,任何具有名为的字段的模型 create_defaults ,它们与 update_or_create() 应使用指定查找中的字段 create_defaults__exact 。

迁移现有的 UUIDField 在MariaDB 10.7+上

在MariaDB 10.7+上, UUIDField 现在创建为 UUID 列,而不是 CHAR(32) 纵队。因此,任何 UUIDField 在Django<5.0中创建的应替换为 UUIDField 支持的子类 CHAR(32) **

class Char32UUIDField(models.UUIDField):
    def db_type(self, connection):
        return "char(32)"

    def get_db_prep_value(self, value, connection, prepared=False):
        value = super().get_db_prep_value(value, connection, prepared)
        if value is not None:
            value = value.hex
        return value

例如::

class MyModel(models.Model):
    uuid = models.UUIDField(primary_key=True, default=uuid.uuid4)

应变为::

class Char32UUIDField(models.UUIDField): ...


class MyModel(models.Model):
    uuid = Char32UUIDField(primary_key=True, default=uuid.uuid4)

运行 makemigrations 命令将生成包含no-op的迁移 AlterField 手术。

其他

  • 这个 instance 无证之辩 BaseModelFormSet.save_existing() 方法被重命名为 obj 。

  • 未登记的人 django.contrib.admin.helpers.checkbox 被移除。

  • 整型字段现在在SQLite上被验证为64位整型,以匹配的行为 sqlite3 。

  • 未登记的人 Query.annotation_select_mask 属性从一组字符串更改为有序的字符串列表。

  • ImageField.update_dimension_fields() 不再在 post_init 发信号通知IF width_field 和 height_field 都没有设置。

  • Now 数据库函数现在使用 LOCALTIMESTAMP 而不是 CURRENT_TIMESTAMP 在甲骨文上。

  • AdminSite.site_header 现在呈现在一个 <div> 标记而不是 <h1> 。屏幕阅读器用户依靠标题元素在页面内导航。有两个 <h1> 元素令人困惑,网站页眉没有任何帮助,因为它在所有页面上都重复出现。

  • 为了提高可访问性,管理员的主内容区域和标题内容区域现在呈现在 <main> 和 <header> 标记而不是 <div> 。

  • 在没有SQL本机支持的数据库上 XOR 操作员, ^ 作为独占OR (XOR )运算符现在返回与奇数个操作数匹配的行,而不是只返回一个操作数。这与MySQL、MariaDB和Python的行为是一致的。

  • 支持的最低版本 asgiref 从3.6.0增加到3.7.0。

  • 支持的最低版本 selenium 从3.8.0增加到4.8.0。

  • 这个 AlreadyRegistered 和 NotRegistered 例外从 django.contrib.admin.sites 至 django.contrib.admin.exceptions 。

  • 支持的最低SQLite版本从3.21.0增加到3.27.0。

  • 支持 cx_Oracle <8.3将被删除。

  • 现在,在应用程序注册表完全填充之前执行SQL查询会引发 RuntimeWarning 。

  • BadRequest 对于非UTF-8编码的请求引发 application/x-www-form-urlencoded 内容类型。看见 RFC 1866 了解更多详细信息。

  • 支持的最低版本 colorama 增加到0.4.6。

  • 支持的最低版本 docutils 增加到0.19。

  • 根据溢出的整数值过滤查询集现在总是返回一个空的查询集。因此,您可能需要使用 ExpressionWrapper() 至 explicitly wrap 在这种情况下对整型字段进行运算。

5.0中弃用的功能

其他

  • 这个 DjangoDivFormRenderer 和 Jinja2DivFormRenderer 过渡表单呈现器已弃用。

  • 传递位置参数 name 和 violation_error_message 至 BaseConstraint 建议使用仅关键字参数,而不推荐使用。

  • request 添加到的签名中 ModelAdmin.lookup_allowed() 。支持 ModelAdmin 不建议使用不接受此参数的子类。

  • 这个 get_joining_columns() 方法论 ForeignObject 和 ForeignObjectRel 已弃用。从Django 6.0开始, django.db.models.sql.datastructures.Join 将不再退回到 get_joining_columns() 。子类应该实现 get_joining_fields() 取而代之的是。

  • 这个 ForeignObject.get_reverse_joining_columns() 方法已弃用。

  • 的默认方案 forms.URLField 将从 "http" 到 "https" 在Django 6.0中。设置 FORMS_URLFIELD_ASSUME_HTTPS 过渡设置 True 选择假设 "https" 在Django 5.x发布周期期间。

  • FORMS_URLFIELD_ASSUME_HTTPS 过渡设置已弃用。

  • 支持呼叫 format_html() 如果没有通过ARG或KWARG,将被移除。

  • 支持 cx_Oracle 不推荐使用,而支持 oracledb 1.3.2+Python驱动程序。

  • DatabaseOperations.field_cast_sql() 不推荐使用,而支持 DatabaseOperations.lookup_cast() 。从Django 6.0开始, BuiltinLookup.process_lhs() 将不再呼叫 field_cast_sql() 。第三方数据库后端应该实现 lookup_cast() 取而代之的是。

  • 这个 django.db.models.enums.ChoicesMeta 元类已重命名为 ChoicesType 。

  • 这个 Prefetch.get_current_queryset() 方法已弃用。

  • 这个 get_prefetch_queryset() 相关管理器和描述符的方法已弃用。从Django 6.0开始, get_prefetcher() 和 prefetch_related_objects() 将不再退回到 get_prefetch_queryset() 。子类应该实现 get_prefetch_querysets() 取而代之的是。

5.0中删除的功能

这些功能已经到了弃用周期的末尾,并在Django 5.0中被删除。

看见 4.0中废弃的功能 有关这些更改的详细信息,包括如何删除这些功能的使用。

  • 这个 SERIALIZE 测试设置已删除。

  • 未登记的人 django.utils.baseconv 模块已移除。

  • 未登记的人 django.utils.datetime_safe 模块已移除。

  • 的缺省值 USE_TZ 设置更改自 False 至 True 。

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

  • 这个 extra_tests 论据 DiscoverRunner.build_suite() 和 DiscoverRunner.run_tests() 被移除。

  • 这个 django.contrib.postgres.aggregates.ArrayAgg , JSONBAgg ,以及 StringAgg 聚合不再返回 [] , [] ,以及 '' 分别在没有行的情况下。

  • 这个 USE_L10N 设置已删除。

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

  • 支持 pytz 时区已删除。

  • 这个 is_dst 参数已从以下位置删除:

    • QuerySet.datetimes()

    • django.utils.timezone.make_aware()

    • django.db.models.functions.Trunc()

    • django.db.models.functions.TruncSecond()

    • django.db.models.functions.TruncMinute()

    • django.db.models.functions.TruncHour()

    • django.db.models.functions.TruncDay()

    • django.db.models.functions.TruncWeek()

    • django.db.models.functions.TruncMonth()

    • django.db.models.functions.TruncQuarter()

    • django.db.models.functions.TruncYear()

  • 这个 django.contrib.gis.admin.GeoModelAdmin 和 OSMGeoAdmin 类被删除。

  • 未登记的人 BaseForm._html_output() 方法被移除。

  • 能够返回一个 str ,而不是 SafeString ,在呈现 ErrorDict 和 ErrorList 被移除。

看见 4.1中弃用的功能 有关这些更改的详细信息,包括如何删除这些功能的使用。

  • 这个 SitemapIndexItem.__str__() 方法被移除。

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

  • 这个 name 的论点 django.utils.functional.cached_property() 被移除。

  • 这个 opclasses 的论点 django.contrib.postgres.constraints.ExclusionConstraint 被移除。

  • 未登记的传球能力 errors=None 至 SimpleTestCase.assertFormError() 和 assertFormsetError() 被移除。

  • django.contrib.sessions.serializers.PickleSerializer 被移除。

  • 的用法 QuerySet.iterator() 在预取相关对象而不提供 chunk_size 不再允许使用参数。

  • 不再允许将未保存的模型实例传递到相关筛选器。

  • created=True 是签名中所要求的 RemoteUserBackend.configure_user() 子类。

  • 支持通过以下方式注销 GET 中的请求 django.contrib.auth.views.LogoutView 和 django.contrib.auth.views.logout_then_login() 被移除。

  • 这个 django.utils.timezone.utc 别名到 datetime.timezone.utc 被移除。

  • 将响应对象和表单/表单集名称传递给 SimpleTestCase.assertFormError() 和 assertFormSetError() 不再被允许。

  • 这个 django.contrib.gis.admin.OpenLayersWidget 被移除。

  • 这个 django.contrib.auth.hashers.CryptPasswordHasher 被移除。

  • 这个 "django/forms/default.html" 和 "django/forms/formsets/default.html" 模板将被删除。

  • 默认的表单和表单集呈现样式更改为基于div的。

  • 传球 nulls_first=False 或 nulls_last=False 至 Expression.asc() 和 Expression.desc() 方法,以及 OrderBy 不再允许使用表达式。