How to pass extra argument to get_serializer_class
Problem Description:
I need to select a serializer based on the value of an object instance. How do I pass an additional argument to get_serializer_class to be able to do the validation there?
def get_serializer_class(self, extra_option):
if extra_option:
return ModelSerializer
return ModelSerializer2
serializer = self.serializer_class(data=request.data, extra_option=smth_instance)
Error:
TypeError: Field.__init__() got an unexpected keyword argument 'extra_option'
If I make a custom class then serializer selection works… maybe this is legit workaround?
def choose_serializer(self, product, data):
if product.document.type == 1:
return Serializer1(product, data=data)
elif product.document.type == 2:
return Serializer2(product, data=data)
serializer = self.choose_serializer(data=request.data, product=product)
Solution – 1
It’s much easier to check the action to decide what serializer to use. Ex.
def get_serializer_class(self):
if self.action == "retrieve":
return ModelOutputSerializer
else:
return ModelDefaultSerializer
Otherwise you likely need to override the action you want the different kwarg on and pass that down, overriding the necessary methods as you go. Ex.
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance, extra_option=...)
return Response(serializer.data)
def get_serializer(self, *args, **kwargs):
serializer_class = self.get_serializer_class(*args, **kwargs)
kwargs.setdefault('context', self.get_serializer_context())
return serializer_class(*args, **kwargs)
def get_serializer_class(self, *args, **kwargs):
if kwargs.pop("extra_option", None):
return ExtraOptionSerializer
else:
return super().get_serializer_class()
Also check out classy DRF for reference: https://www.cdrf.co/3.13/rest_framework.viewsets/ModelViewSet.html#retrieve.
Edit: also self.serializer_class
defaults to whatever you define on the view set so you likely want to instead call self.get_serializer_class(...)
like you did with your custom method above.