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

2024-10-01 09:23:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用的是django rest框架。我有一个有关系的模特。我只想在用户点击/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')

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

短:

^{pr2}$

长:

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

我想做的是能够根据查询参数(url)在它们之间切换。当ID不存在时,我试图将serializer_类设置为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。在


Tags: selfiddatamodeltitlealldatasetclass
3条回答

谢谢你,本杰明。这并不是我想要的。最终我要做的是(使用与上面相同的序列化程序):

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)

在网址.py公司名称:

^{pr2}$

可以通过重写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

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

您可以将序列化器_类的list create api视图用作ShortDataSetSerializer。所以当你得到数据列表时,它会有修订的次数。另外,如果希望post请求在同一个url上工作,则必须重写get_serializer_class方法,以根据请求类型设置序列化程序_类。在

对于retrieve视图,可以将serializer_类用作DataSetSerializer。它将有一个修订列表,而不是计数。在

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

另外,您可以覆盖viewset上的list和retrieve方法,但是我更喜欢使用基于类的视图,因为DRF有很多附加到请求函数上的功能,比如get、put等(或者list,detail),最好不要重写它们。在

相关问题 更多 >