How do I set a different Serializer for list and detail view while using viewsets.ModelViewSet
and HyperlinkedSerializer
?
I see how to do it with viewsets.ViewSet
by defining list
and retrive
, (here's an example) but I don't know how to elegantly adapt it to viewsets.ModelViewSet
I've adapted an answer from "Django rest framework, use different serializers in the same ModelViewSet" that serves me very well, and I hope you'll find useful:
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()
In this case, you're just specifying your two serializers and using the one depending on the action. However, this can be made more general (for all actions) as follows:
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()
Viewsets extend the class GenericAPIView, so you can use this part of the documentation to solve your problem. Basically, what you need is to override get_serializer_class and to return a different serializer based on your request.
I've created this small package for this job. drf_custom_viewsets.
It has CustomSerializerViewSet
, which inherits from ModelViewSet
, which lets you set different serializers for different actions.