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
The serializers in REST framework work very similarly to Django's Form and ModelForm classes. The two major serializers that are most popularly used are ModelSerializer and HyperLinkedModelSerialzer.
APIView allow us to define functions that match standard HTTP methods like GET, POST, PUT, PATCH, etc. Viewsets allow us to define functions that match to common API object actions like : LIST, CREATE, RETRIEVE, UPDATE, etc.
The root QuerySet provided by the Manager describes all objects in the database table. Usually, though, you'll need to select only a subset of the complete set of objects. The default behavior of REST framework's generic list views is to return the entire queryset for a model manager.
The HyperlinkedModelSerializer class is similar to the ModelSerializer class except that it uses hyperlinks to represent relationships, rather than primary keys. By default the serializer will include a url field instead of a primary key field.
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'): return self.action_serializers.get(self.action, self.serializer_class) return super(MyModelViewSet, self).get_serializer_class()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With