Ozgur Akcali February 2016

Django Rest Framework dynamic field list on Serializer for list of items

In django rest framework, it is possible to dynamically remove fields at runtime with a custom __init__ method on the serializer. I am using this technique to remove certain fields from the serializer depending on the relation of the requesting user and requested resource, as follows:

def __init__(self, *args, **kwargs):
    # get request from context, initialize super class etc.

    if request.user != self.instance.user:
        self.fields.pop('private field')

This approach works well when retrieving a single object, but when I am listing objects, the serializer is initialized with a list of items, hence self.instance does not point to a specific instance on init method, hence I can not make the comparison I want.

Any suggestions on how I can achieve what I want when listing objects?


hectorcanto February 2016

You should call the Serializer with the keyword many=True so each element is processed independently, and pass through your custom init. Something like:

serialization = MySerializer(data=request.data, many=True)

If you don't now if you will handle an element or a list of elements you should either convert the elemente into a list, only receive lists (1 to many) or detect the case and define many accordingly.

t_io February 2016

You could write a Serializer mixin where you overwrite to_representation.

from rest_framework import serializers
from collections import OrderedDict

class MySerializerMixin(serializers.Serializer):
    def to_representation(self, instance):
        original_representation = super(MySerializerMixin, self).to_representation(instance)
        final_representation = OrderedDict()
        # don't append keys you don't want for serialization
        for k,v in original_representation.iteritems():
            if k not 'something':
                final_representation[k] = v
        return final_representation

And use it like this when defining your serializer.

class SomeSerializer(MySerializerMixin, serializers.ModelSerializer):

I use something similar to remove all None values but with some adjustments it should also fit your needs.

Post Status

Asked in February 2016
Viewed 2,008 times
Voted 8
Answered 2 times


Leave an answer