You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django DRF中为Post查询集添加author_username自定义属性?

在DRF中为Post序列化器添加author_username字段(不修改模型)

场景

作为DRF新手,我现有Post和User两个模型,相关代码如下:

Post模型

class Post(models.Model):
    """
        Post model
    """

    title = models.CharField(max_length=250)
    body = models.TextField()
    author = models.ForeignKey(settings.AUTH_USER_MODEL,
                               on_delete=models.CASCADE,
                               related_name='forum_posts')
    parent_post = models.ForeignKey('self',
                                    on_delete=models.CASCADE,
                                    blank=True,
                                    null=True)
    time_stamp = models.DateTimeField(default=timezone.now)

    objects = models.Manager()

Post序列化器

class PostSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.Post
        fields = ('id', 'title', 'body', 'parent_post', 'author', 'time_stamp')
        extra_kwargs = {'id': {'read_only': True},
                        'author': {'read_only': True}}

视图类

class PostList(generics.ListCreateAPIView):
    permission_classes = [IsAuthenticatedOrReadOnly]
    queryset = models.Post.objects.all()
    serializer_class = serializers.PostSerializer

需求

返回Post数据时,为每个对象添加author_username字段,值为对应作者的用户名,且不修改模型添加冗余字段。期望返回的JSON示例:

{
    "id": 1,
    "title": "Example post",
    "body": "Example post",
    "author": 1,
    "parent_post": null,
    "time_stamp": "2022-01-01T00:00:00Z",
    "author_username": "testUser"
}

实现方法

方法一:使用SerializerMethodField

适合需要自定义逻辑的灵活场景:

class PostSerializer(serializers.ModelSerializer):
    # 定义自定义字段
    author_username = serializers.SerializerMethodField()

    # 实现字段取值逻辑,obj为当前Post实例
    def get_author_username(self, obj):
        return obj.author.username

    class Meta:
        model = models.Post
        # 将新字段加入返回字段列表
        fields = ('id', 'title', 'body', 'parent_post', 'author', 'time_stamp', 'author_username')
        extra_kwargs = {'id': {'read_only': True},
                        'author': {'read_only': True}}

方法二:使用CharField+source参数

无需额外逻辑时,这种方式更简洁:

class PostSerializer(serializers.ModelSerializer):
    # 通过source直接关联到author的username字段,设置read_only避免提交时被修改
    author_username = serializers.CharField(source='author.username', read_only=True)

    class Meta:
        model = models.Post
        fields = ('id', 'title', 'body', 'parent_post', 'author', 'time_stamp', 'author_username')
        extra_kwargs = {'id': {'read_only': True},
                        'author': {'read_only': True}}

性能优化(可选)

当查询大量Post数据时,为避免N+1查询问题,在视图中用select_related预取关联的author数据:

class PostList(generics.ListCreateAPIView):
    permission_classes = [IsAuthenticatedOrReadOnly]
    # 预取author关联对象,减少数据库查询次数
    queryset = models.Post.objects.all().select_related('author')
    serializer_class = serializers.PostSerializer

内容的提问来源于stack exchange,提问作者coderman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 18:50:45