Categories
Django Python

Django REST Framework: Dynamic Fields in Serializers

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:

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.

Now the second serializer will get the request too and we can use the same way to customize it!

7 replies on “Django REST Framework: Dynamic Fields in Serializers”

No longer the recommended way.

 

The recommended way is

I think you misunderstood the purpose. The field is added based on whether a certain GET parameter is passed or not. SerializerMethodField is always available.

I’m having an issue where the context is not available to the __init__ if the serializer is a nested serializer:

Do you know how to forward the context along?

the following code yields this error:
reque st = kwargs[‘context’][‘request’]
KeyError: ‘context’

This is not the canonical way to do this; you are meant to define different serializer classes for every case, and then utilize get_serializer_class in the viewset for your conditional logic. If it was meant to be done the way you describe, it would have been easy enough for the drf team to include a canonical way for you to perform this task from within the serializer.

You may feel it’s heavy-handed to define a serializer class for every layer of granularity you want to include in your response, but I would counter such a sentiment by asking; why is your API spec so inconsistent? Why should a consumer of your API need to deal with so many small variations in your responses? If some fields are computationally expensive to generate, perhaps you would be better served by making this it’s own endpoint altogether? If they aren’t, why not simply include them in every response?

I cannot fathom a convincing use-case for this pattern.

Comments are closed.