Django 3.2 带来的激动人心的新功能
2023-09-18 14:12:31
Django 3.2 即将到来,它带来了众多新功能,让 Django 开发者兴奋不已。通常情况下,Django 的新版本不会带来太多惊喜(这本身就是一件好事),但这次我们在对象关系映射 (ORM) 中看到了一些特别令人振奋的补充。以下是我在 Django 3.2 中最喜欢的几个功能:
1. 子查询与预取功能的改进
Django 3.2 中对子查询和预取功能进行了重大改进。现在,您可以使用 django.db.models.Exists
和 django.db.models.DoesNotExist
子查询来检查相关对象是否存在或不存在。这对于优化复杂查询非常有用。
例如,假设您有一个 Post
模型和一个 Comment
模型。您可能希望获得所有没有评论的帖子。在 Django 3.2 之前,您需要使用如下代码:
from django.db.models import Exists, OuterRef
posts = Post.objects.annotate(
has_comments=Exists(Comment.objects.filter(post=OuterRef('pk')))
).filter(has_comments=False)
现在,您可以使用更简洁的 DoesNotExist
子查询:
from django.db.models import DoesNotExist
posts = Post.objects.annotate(
has_comments=DoesNotExist(Comment.objects.filter(post=OuterRef('pk')))
).filter(has_comments=True)
您还可以使用预取来优化嵌套查询。在 Django 3.2 之前,您需要使用如下代码预取评论:
from django.db.models import Prefetch
posts = Post.objects.prefetch_related('comments')
现在,您可以使用 select_related
来预取评论:
posts = Post.objects.select_related('comments')
2. 模型中 F() 表达式的改进
Django 3.2 中对模型中 F()
表达式进行了改进。现在,您可以使用 F()
表达式来更新模型字段。例如,假设您有一个 Post
模型和一个 views
字段。您可以使用如下代码增加帖子的浏览量:
from django.db.models import F
Post.objects.filter(pk=1).update(views=F('views') + 1)
3. 新增 Model.from_queryset() 方法
Django 3.2 引入了新的 Model.from_queryset()
方法,它允许您从查询集创建新模型。这对于创建嵌套序列化程序或在视图中处理复杂查询非常有用。
例如,假设您有一个 Post
模型和一个 Comment
模型。您可能希望创建一个序列化程序,它将帖子的标题和前 5 条评论返回为嵌套列表。您可以使用如下代码:
from django.db.models import Model, from_queryset
class PostWithCommentsSerializer(Model):
title = serializers.CharField(source='title')
comments = serializers.SerializerMethodField()
def get_comments(self, obj):
return CommentSerializer(obj.comments.all()[:5], many=True).data
4. 外键上的 on_delete 行为的改进
Django 3.2 改进了外键上的 on_delete
行为。现在,您可以指定 PROTECT
行为,当相关对象被删除时,这将引发 ProtectedError
。这对于防止数据丢失非常有用。
例如,假设您有一个 Post
模型和一个 Comment
模型。您可能希望确保在删除帖子时不会删除评论。您可以使用如下代码:
class Post(models.Model):
...
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.PROTECT)
5. 新的 UUIDField 字段类型
Django 3.2 引入了新的 UUIDField
字段类型,它允许您将 UUID 值存储在模型字段中。这对于生成唯一的 ID 或与其他系统集成非常有用。
例如,假设您有一个 Post
模型,您希望使用 UUID 作为主键。您可以使用如下代码:
from django.db import models
from uuid import uuid4
class Post(models.Model):
id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
...
结论
Django 3.2 是一个激动人心的版本,它为 Django 开发人员带来了许多新功能。这些功能将帮助您编写更有效、更健壮的 Django 代码。我们迫不及待地想看到这些功能如何被用来构建新的和创新的 Django 应用程序。