我正在为后端创建一个带有django rest框架的博客。 我有一个帖子模型,它有一个"描述"文本字段。我想将此模型用于"显示所有帖子的列表"和"显示单个帖子"。我不希望为博客页面发送描述字段,而只为单个帖子页面发送描述字段。这是我的代码:
帖子模型:
class Posts(models.Model):
title = models.CharField(max_length=255)
subtitle = models.CharField(max_length = 255)
description = models.TextField(default = "")
发布视图集:
class PostsViewSet(viewsets.ModelViewSet):
serializer_class = serializers.PostsSerializer
queryset = models.Posts.objects.all()
后序列化程序:
class PostsSerializer(serializers.ModelSerializer):
class Meta:
model = models.Posts
fields = '__all__'
注意:当我去 http://example.com/Posts 时,我喜欢看到所有没有描述的帖子。 但对于 http://example.com/Posts/1,我想要描述以及其他字段。
可以通过多种方法
实现方法-1:重写序列化程序的__init__()
方法
class PostsSerializer(serializers.ModelSerializer):
class Meta:
model = models.Posts
fields = '__all__'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if 'view' in self.context and self.context['view'].action == 'list':
self.fields.pop('description')
您正在使用viewset
类作为视图。因此,我们可以从.action
属性中获取特定操作
方法2:使用不同的序列化程序(如Van Onsem提到的@Willem并为此调整get_serializer_class()
# serializers.py
class PostDetailSerializer(serializers.ModelSerializer):
class Meta:
model = models.Posts
fields = '__all__'
class PostListSerializer(PostDetailSerializer):
class Meta:
model = models.Posts
exclude = ('description',)
# views.py
class PostsViewSet(viewsets.ModelViewSet):
serializer_class = serializers.PostsSerializer
queryset = models.Posts.objects.all()
def get_serializer_class(self):
if self.action == 'list':
return PostListSerializer
return PostDetailSerializer
解决方案可能是引入两个序列化程序,一个用于列表,一个用于详细信息页面。
因此,它可以看起来像:
class PostDetailSerializer(serializers.ModelSerializer):
class Meta:
model = models.Posts
fields = '__all__'
然后我们可以将列表序列化程序编写为:
class PostListSerializer(PostDetailSerializer):
class Meta:
model = models.Posts
exclude = ('description', )
因此,现在,如果对PostDetailSerializer
进行自定义更改(例如,名称的呈现方式(,那么这也将对列表的序列化方式产生影响。如果我们想让它们彼此"独立",我们也可以只制作两个没有这种继承的序列化器。
那么我们可以提出两种观点:
class PostList(generics.ListCreateAPIView):
queryset = models.Post.objects.all()
serializer_class = PostListSerializer
class RetrievePostView(generics.RetrieveAPIView):
queryset = models.Post.objects.all()
serializer_class = PostDetailSerializer