假设我们有一个Django Rest Framework端点:
class Comment(models.Model):
article = models.ForeignKey(Article)
author = models.ForeignKey(Author)
content = models.TextField()
class CommentsListCreateView(
mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView
):
allowed_methods = ['GET', 'POST']
serializer_class = CommentSerializer
queryset = Comment.objects.all()
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
我希望端点像这样工作:
[{
article: {id: 1, title: '100 things about'},
author: {id: 1, name: 'Miguel'},
content: 'Blah blah blah'
}]
POST {article: 1, author: 1, content: 'Blah blah blah again'}
->
{
article: {id: 1, title: '100 things about'},
author: {id: 1, name: 'Miguel'},
content: 'Blah blah blah again'
}
请注意,我将obj ID作为参数发布,但是服务器返回了obj详细信息。
这种方法可以吗?
现在我有两个序列化程序CommentListSerializer和CommentCreateSerializer用于列表和视图,但是对我来说看起来很丑。我敢打赌,还有许多其他想法会更好,但没有您的帮助我将无法实现=)谢谢。
答案 0 :(得分:0)
这是一种非常有效的方法,尤其是如果您想让客户端不必执行额外的请求来检索相关数据和服务器,而不必通过不必要地解析有效负载来提取关系的ID。
如果我的理解正确,那么您正在寻找更好的解决方案?在这种情况下,我可以建议以下内容:
class ArticleSerializer(ModelSerializer):
class Meta:
model = Article
fields = ["id", "title"]
class AuthorSerializer(ModelSerializer):
class Meta:
model = Author
fields = ["id", "name"]
class CommentSerializer(ModelSerializer):
class Meta:
model = Comment
fields = ["article", "author", "content"]
def to_representation(self, instance):
representation = self.to_representation(instance)
representation.update({
"article": ArticleSerializer(instance.article).data,
"author": AuthorSerializer(instance.author).data
})
return representation
class CommentsListCreateView(ListCreateAPIView):
serializer_class = CommentSerializer
queryset = Comment.objects.all()
我没有运行此代码,因此可能会有一些错误,但这是一般的想法。我通常更喜欢使用HyperlinkedModelSerializer
和HyperlinkedRelatedField
,这样客户端就不必自己重建URL,而是可以自动将它们解析为实例。这通常导致我继承HyperlinkedRelatedField
的子类并覆盖其to_representation
方法。这样,我可以传递要用于将输出序列化为参数的序列化器。大概的草稿如下:
class CustomHyperlinkRelatedField(HyperlinkRelatedField):
self.serializer_class = None
def __init__(self, view_name=None, **kwargs):
self.serializer_class = kwargs.pop(
"serializer_class", self.serializer_class
)
super().__init__(view_name=view_name, **kwargs)
def to_representation(self, instance):
if not self.serializer_class:
return super().to_representation(instance)
obj = get_object_or_404(queryset, pk=instance.pk)
request = self.context["request"]
return self.serializer_class(obj, context={"request": request}).data
class SomeSerializer(Serializer):
relation = CustomHyperlinkedRelatedField(
queryset=SomeModel.objects.all(),
serializer_class=SomeModelSerializer
)