Here’s the use case, I need to add some extra fields to my serializer depending on a request. For example, if the query string contains “extra=true”, then add the extra fields. Luckily, serializers get a “context” argument when they are initialized. We can use this to customize our serializers as needed.
The fields defined on a serializer are available in a instance variable named “fields”. So we can add/delete/edit fields from it. Let’s see an example:
1 2 3 4 5 6 7 8 9 10 11 12 |
class OrderSerializer(ModelSerializer): payments = PaymentSerializer(many=True, read_only=True) evaluations = OrderEvaluationSerializer(many=True, read_only=True) def __init__(self, *args, **kwargs): super(OrderSerializer, self).__init__(*args, **kwargs) request = kwargs['context']['request'] include_address = request.GET.get('include_address', False) if include_address: self.fields['user_location'] = UserLocationSerializer(read_only=True) |
Please note, here we have used another serializer (UserLocationSerializer) from inside our main serializer. The second one is being initialized by us. So it would not get the context. If we need to do something down there as well, then we need to pass it ourselves.
1 2 3 4 5 6 7 8 9 10 11 12 |
class OrderSerializer(ModelSerializer): payments = PaymentSerializer(many=True, read_only=True) evaluations = OrderEvaluationSerializer(many=True, read_only=True) def __init__(self, *args, **kwargs): super(OrderSerializer, self).__init__(*args, **kwargs) request = kwargs['context']['request'] include_address = request.GET.get('include_address', False) if include_address: self.fields['user_location'] = UserLocationSerializer(read_only=True, context=kwargs['context']) |
Now the second serializer will get the request too and we can use the same way to customize it!