如何使用Django Rest Framework为列表和详细信息视图设置不同的Serializer?

时间:2014-07-17 17:18:02

标签: django django-rest-framework

如何在使用viewsets.ModelViewSetHyperlinkedSerializer时为列表和详细信息视图设置不同的序列化程序?

我通过定义viewsets.ViewSetlist,(here's an example)来了解如何使用retrive进行操作,但我不知道如何优雅地适应它viewsets.ModelViewSet

4 个答案:

答案 0 :(得分:32)

我已经改编了“Django rest framework, use different serializers in the same ModelViewSet”的答案,这对我很有帮助,我希望你能找到有用的东西:

class MyModelViewSet(viewsets.MyModelViewSet):

    queryset = MyModel.objects.all()
    serializer_class = MyModelListSerializer
    detail_serializer_class = MyModelDetailSerializer

    def get_serializer_class(self):
        if self.action == 'retrieve':
            if hasattr(self, 'detail_serializer_class'):
                return self.detail_serializer_class

        return super(MyModelViewSet, self).get_serializer_class()

在这种情况下,您只需指定两个序列化程序并使用取决于操作的序列化程序。但是,这可以更加通用(对于所有操作)如下:

class MyModelViewSet(viewsets.MyModelViewSet):

    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer

    action_serializers = {
        'retrieve': MyModelDetailSerializer,
        'list': MyModelListSerializer,
        'create': MyModelCreateSerializer
    }

    def get_serializer_class(self):

        if hasattr(self, 'action_serializers'):
            if self.action in self.action_serializers:
                return self.action_serializers[self.action]

        return super(MyModelViewSet, self).get_serializer_class()

答案 1 :(得分:1)

Viewsets扩展了GenericAPIView类,因此您可以使用this part of the documentation来解决您的问题。基本上,您需要的是覆盖 get_serializer_class 并根据您的请求返回不同的序列化程序。

答案 2 :(得分:0)

我为这份工作创造了这个小包装。 drf_custom_viewsets

它有CustomSerializerViewSet,它继承自ModelViewSet,可让您为不同的操作设置不同的序列化程序。

答案 3 :(得分:0)

从 2021 年开始,我将采用不同的方式,更好、更通用的方法是执行以下操作:

class PlayersListViewSet(viewsets.ModelViewSet):
    queryset = Player.objects.all()
    serializer_class = PlayersListSerializer
    http_method_names = ['get', 'post']
    pagination_class = None
    filter_backends = [filters.OrderingFilter]
    ordering_fields = ['name']

    serializer_class_by_action = {
        'retrieve': PlayersDetailSerializer,
        'list': PlayersListSerializer,
    }

    def get_serializer_class(self):

        if hasattr(self, 'serializer_class_by_action'):
            return self.serializer_class_by_action.get(self.action, self.serializer_class)

        return super(MyModelViewSet, self).get_serializer_class()

    def get_queryset(self):
        queryset = Player.objects.all()
        team_id = self.request.query_params.get('team', None)

        if team_id:
            try:
                queryset = queryset.filter(team=team_id)
            except ValueError:
                raise exceptions.ParseError()
        return queryset

这里的action是序列化器使用的方法,listdef listretrievedef retrieve等等..< /p>