返回

Django 3.2 带来的激动人心的新功能

见解分享

Django 3.2 即将到来,它带来了众多新功能,让 Django 开发者兴奋不已。通常情况下,Django 的新版本不会带来太多惊喜(这本身就是一件好事),但这次我们在对象关系映射 (ORM) 中看到了一些特别令人振奋的补充。以下是我在 Django 3.2 中最喜欢的几个功能:

1. 子查询与预取功能的改进

Django 3.2 中对子查询和预取功能进行了重大改进。现在,您可以使用 django.db.models.Existsdjango.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 应用程序。