繁体   English   中英

如何在同一模型中使用两个不同的模型序列化器?

[英]How Can I Use Two Different Model Serializers With the Same Model?

我正在使用django-rest-framework。 我有一个有关系的模型。 我只想在用户点击/modelname/ URL时显示相关项的计数,但是当用户点击/modelname/1/处的特定模型实例时显示完整的相关集。

几乎可以得到我想要的。

我有两个序列化器,如下所示:

class DataSetSerializer(serializers.ModelSerializer):
    revisions = serializers.RelatedField(source='datasetrevision_set', many=True)

    class Meta:
        model = DataSet
        fields = ('id', 'title', 'revisions')

class ShortDataSetSerializer(serializers.ModelSerializer):

    class Meta:
        model = DataSet
        fields = ('id', 'title', 'revisions')

如果使用简短版本,则会得到修订计数(这是一个计算字段)。 如果使用长版本,则会获得相关项目的完整列表作为“修订”。

短:

[{"id": 1, "title": "My Data Set", "revisions": 0}]

长:

[{"id": 1, "title": "My Data Set", "revisions": ["Data Set v1", "Data Set v2"]}]

我想做的是能够根据查询参数(URL)在它们之间切换。 当ID不存在时,我尝试将serializer_class设置为ShortDataSetSerializer,但它覆盖了所有情况,而不仅仅是非ID情况。

class DataSetViewSet(viewsets.ModelViewSet):
    serializer_class = DataSetSerializer
    model = DataSet

    def get_queryset(self):
       try:
           id = self.kwargs['id']
           queryset = DataSet.objects.filter(id=id)
       except KeyError:
           queryset = DataSet.objects.all()
           # We want to only list all of the revision data if we're viewing a
           # specific set, but this overrides for all cases, not just the one
           # we want.
           self.serializer_class = ShortDataSetSerializer
       return queryset

有什么办法可以使我工作吗? 我意识到我可能会以一种完全荒谬的方式来解决这个问题,但是似乎应该有一个简单的解决方案。

与我正在使用的实际数据相比,我给出的数据示例相当简洁。 最终目标是在列表视图中显示字段的子集,并在GET中为特定ID显示每个字段。 这是一个只读API,因此我不必担心POST / PUT / DELETE。

您可以通过重写get_serializer_class方法来实现:

class DataSetViewSet(viewsets.ModelViewSet):
    model = DataSet

    def get_queryset(self):
       queryset = DataSet.objects.all()
       if self.kwargs.get('id'):
          queryset = queryset.filter(pk=self.kwargs.get('id'))
       return queryset

    def get_serializer_class(self):
       return DataSetSerializer if 'id' in self.kwargs else ShortDataSetSerializer

我认为解决此问题的一个简单方法是使用基于类的通用视图而不是视图集。

您可以使用带有serializer_class作为ShortDataSetSerializer的列表创建api视图。 因此,当您获得数据列表时,它将具有修订计数。 另外,如果您希望发布请求在相同的url上工作,则必须重写get_serializer_class方法以根据请求类型设置serializer_class。

对于检索视图,可以将serializer_class用作DataSetSerializer。 它将有一个修订列表,而不是计数。

在DRF文档网站上签出通用视图api指南。

此外,您可以覆盖列表并在视图集上检索方法,但是我更喜欢使用基于类的视图,因为DRF在请求函数(如get,put等)(或列表,详细信息)上附加了许多附加功能,并且它最好不要覆盖它们。

谢谢你,本杰明。 那没有做我一直在寻找的东西。 最终,我要做的是(使用与上述相同的序列化器):

class DataSetViewSet(viewsets.ModelViewSet):
    model = DataSet

    def list(self, request):
        queryset = DataSet.objects.all()
        serializer = ShortDataSetSerializer(queryset, many=True)
        return Response(serializer.data)

    def detail(self, request, id=None):
        queryset = DataSet.objects.get(id=id)
        serializer = DataSetSerializer(queryset)
        return Response(serializer.data)

并在urls.py中:

url(r'^sets/$', views.DataSetViewSet.as_view({'get': 'list'})),
url(r'^sets/(?P<id>\d+)/$', views.DataSetViewSet.as_view({'get': 'detail'})),

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM