如何在Django 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
相关产品推荐
相关产品推荐

