Django 6.0 已于 2025 年 12 月 3 日正式发布,为这个久经考验的Python Web 框架开启了新的篇章。本次版本更新带来了多项旨在提升开发效率与应用安全性的重要功能。
使用 django-upgrade 升级项目
如果你计划从 Django 5.2 或更早版本进行升级,可以借助工具 django-upgrade 来简化流程。该工具能够自动更新旧版 Django 代码以适配新特性,并修复包括针对 Django 6.0 在内的多个弃用警告。
模板局部定义(Template Partials)
Django 模板语言现在引入了模板局部定义功能,通过新的 {% partialdef %} 和 {% endpartialdef %} 标签,开发者可以在模板文件中定义并重用命名的代码片段。
在同一模板中重复使用局部定义
以下示例展示了如何在同一个模板内定义并多次使用一个名为 filter_controls 的局部定义,有效避免了代码重复。
<section id="videos">
{% partialdef filter_controls %}
<form>
{{ filter_form }}
</form>
{% endpartialdef %}
{% partial filter_controls %}
<ul>
{% for video in videos %}
<li>
<h2>{{ video.title }}</h2>
...
</li>
{% endfor %}
</ul>
{% partial filter_controls %}
</section>
通过为 partialdef 标签添加 inline 选项,可以让定义在原地直接渲染,进一步简化代码结构。
<section id="videos">
{% partialdef filter_controls inline %}
<form>
{{ filter_form }}
</form>
{% endpartialdef %}
<ul>
{% for video in videos %}
<li>
<h2>{{ video.title }}</h2>
...
</li>
{% endfor %}
</ul>
{% partial filter_controls %}
</section>
单独渲染局部定义
局部定义也支持单独渲染,非常适合与 HTMX 等前端库配合实现局部页面更新。以下模板定义了一个 view_count 局部,它通过 HTMX 属性定期向特定视图发起请求以刷新数据。
{% load django_htmx %}
<!doctype html>
<html>
<body>
<h1>{{ video.title }}</h1>
<video width="1280" height="720" controls>
<source src="{{ video.file.url }}" type="video/mp4">
Your browser does not support the video tag.
</video>
{% partialdef view_count inline %}
<section
class="view-count"
hx-trigger="every 1s"
hx-swap="outerHTML"
hx-get="{% url 'video-view-count' video.id %}"
>
{{ video.view_count }} views
</section>
{% endpartialdef %}
{% htmx_script %}
</body>
</html>
对应的视图可以通过在模板名后附加 #局部定义名 的方式来仅渲染指定的局部。
from django.shortcuts import render
def video(request, video_id):
...
return render(request, "video.html", {"video": video})
def video_view_count(request, video_id):
...
return render(request, "video.html#view_count", {"video": video})
任务框架(Tasks Framework)
Django 6.0 内置了一个全新的任务框架,用于在 HTTP 请求-响应周期之外执行后台作业,例如发送邮件或处理数据。这为后端开发提供了标准化的异步任务处理接口。
使用新的 @task 装饰器可以轻松定义任务:
from django.tasks import task
@task
def resize_video(video_id):
...
通过 Task.enqueue() 方法将任务加入队列:
from example.tasks import resize_video
def upload_video(request):
...
resize_video.enqueue(video.id)
...
执行任务
Django 核心目前提供了两个用于开发和测试的后端:立即执行的 ImmediateBackend 和用于测试断言的 DummyBackend。对于生产环境,需要集成第三方后端,例如 django-tasks 包提供的 DatabaseBackend。
配置 DatabaseBackend 的步骤如下:
- 安装
django-tasks 包。
- 将应用添加到
INSTALLED_APPS:
INSTALLED_APPS = [
# ...
"django_tasks",
"django_tasks.backends.database",
# ...
]
- 在
settings.py 中配置任务后端:
TASKS = {
"default": {
"BACKEND": "django_tasks.backends.database.DatabaseBackend",
},
}
- 运行迁移以创建数据库表。
- 使用
./manage.py db_worker 命令启动工作进程。
内容安全策略(CSP)支持
Django 现已内置对内容安全策略(CSP)的支持,该策略能有效防御跨站脚本(XSS)等代码注入攻击。这为提升Web应用安全性提供了强大且便捷的工具。
启用CSP需要两个步骤:
- 将 CSP 中间件添加到
MIDDLEWARE 设置中:
MIDDLEWARE = [
# ...
"django.middleware.csp.ContentSecurityPolicyMiddleware",
# ...
]
- 通过
SECURE_CSP 或 SECURE_CSP_REPORT_ONLY 设置配置策略。例如,一个基于随机数(Nonce)的严格策略可以这样配置:
from django.utils.csp import CSP
SECURE_CSP_REPORT_ONLY = {
"script-src": [CSP.NONCE, CSP.STRICT_DYNAMIC],
"object-src": [CSP.NONE],
"base-uri": [CSP.NONE],
}
随机数生成(Nonce Generation)
CSP 中间件会自动为每个请求生成随机数。要在模板中使用,需:
- 添加
csp 上下文处理器:
TEMPLATES = [{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"OPTIONS": {
"context_processors": [
# ...
"django.template.context_processors.csp",
],
},
}]
- 在
<script> 和 <style> 标签中添加 nonce 属性:
<script src="{% static 'app.js' %}" type="module" nonce="{{ csp_nonce }}"></script>
邮件 API 更新
邮件处理现已基于 Python 3.6 引入的现代邮件 API(email.message.EmailMessage)重构。对于常规使用(如 send_mail() 和 EmailMessage),API 保持兼容,但底层实现更健壮、更简洁。
使用 MIMEPart 更容易地添加内联附件
新 API 简化了在 HTML 邮件中添加内联图片附件的流程:
import email.utils
from email.message import MIMEPart
from django.core.mail import EmailMultiAlternatives
message = EmailMultiAlternatives(
subject="可爱熊猫警报",
body="这里有一张可爱的熊猫照片送给你!",
from_email="cute@example.com",
to=["fans@example.com"],
)
with open("panda.jpg", "rb") as f:
panda_jpeg = f.read()
cid = email.utils.make_msgid()
inline_image = MIMEPart()
inline_image.set_content(
panda_jpeg,
maintype="image",
subtype="jpeg",
disposition="inline",
cid=cid,
)
message.attach(inline_image)
message.attach_alternative(
f'<h1>可爱熊猫宝宝警报!</h1><img src="cid:{cid[1:-1]}">',
"text/html",
)
位置参数在 django.core.mail API 中的弃用
为了提高代码可读性,django.core.mail 模块中的多个函数和类现在要求对不常用的参数使用关键字参数。使用位置参数将触发弃用警告。例如,send_mail 的调用应更新为:
from django.core.mail import send_mail
send_mail(
subject="🐼 本周的熊猫",
body="本周的熊猫是 Po Ping,sha-sha booey!",
from_email="updates@example.com",
recipient_list=["adam@example.com"],
fail_silently=True,
)
工具 django-upgrade 可自动完成此项修复。
扩展自动 shell 导入
./manage.py shell 命令现在除了自动导入所有模型外,还会默认导入一批常用的工具,如 django.conf.settings、django.db.connection、django.utils.timezone 等,方便开发者进行交互式调试和探索。
保存时动态字段刷新
对于由数据库生成的字段(如 GeneratedField 或通过表达式赋值的字段),在调用 save() 方法后,Django 现在会在支持 RETURNING 子句的数据库后端(SQLite, PostgreSQL, Oracle)上自动刷新其值。对于不支持的后端(MySQL, MariaDB),字段会被标记为延迟加载,在下次访问时自动从数据库获取新值。这消除了手动调用 refresh_from_db() 的需要。
通用 StringAgg 聚合函数
原先仅限 PostgreSQL 使用的 StringAgg 聚合函数(用于将值连接成字符串)现在已推广到所有数据库后端。需要从 django.db.models 导入,并且 delimiter 参数需使用 Value() 表达式包装。
from django.db.models import StringAgg, Value
videos = Video.objects.annotate(
chapter_ids=StringAgg("chapter", delimiter=Value(",")),
)
BigAutoField 作为默认主键类型
DEFAULT_AUTO_FIELD 设置的默认值现改为 BigAutoField,新项目和应用将默认使用 64 位整数主键,从根本上避免了大规模应用可能遇到的“主键耗尽”问题。现有项目可以移除显式的 DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" 设置。
模板变量 forloop.length
在模板的 for 循环中,现在可以使用新的 forloop.length 变量来直接获取迭代序列的长度,例如 {{ forloop.counter }}/{{ forloop.length }}。
querystring 模板标签增强
Django 5.1 引入的 {% querystring %} 标签得到两项改进:
- 始终在返回的查询字符串前加上
?,确保空参数映射时能正确清除现有查询参数。
- 支持接受多个映射(如
QueryDict 或 dict)作为位置参数进行合并,后出现的参数具有更高优先级。