Skip to content

Remove Field from Django Rest Framework Serializer Output

Problem

We need to remove a field from Django Rest Framework serializer output. There could be many reasons for this. For example:

  • Authorization - user is not authorized to see certain data.
  • Feature toggle - we want certain feature to be available based on a feature flag (toggle)

Solution

Override the default to_representation method to drop the field from the output:

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User

    def to_representation(self, instance):
        representation = super().to_representation(instance)
        representation.pop('salary')
        return representation

Discussion

To make the solution more reusable, you could create a mix-in class:

class DropFieldsSerializerMixin:
    def drop_representation_fields(self, representation:dict, fields):
        """Drop a one or more fields from serializer representation"""
        fields = (fields,) if type(fields) == str else fields
        for remove_field in fields:
            representation.pop(remove_field)

You could use the mix-in to remove (drop) fields from the serializer output:

class UserSerializer(serializers.ModelSerializer, DropFieldsSerializerMixin):
    def to_representation(self, instance):
        representation = super().to_representation(instance)
        self.drop_representation_fields(representation, 'salary')
        return representation

A unit test (pytest) to test our drop serializer field mix-in might look like:

from mylib.django.restframework import serializers

class MySerializer(serializers.DropFieldsSerializerMixin):
    pass

def test_drop_representation_fields_removes_single_field():
    data = dict(city='Sofia', name='John Doe', salary=1e6)
    expected = dict(city='Sofia', name='John Doe')

    serializer = MySerializer()
    serializer.drop_representation_fields(data, 'salary')

    assert data == expected

def test_drop_representation_fields_removes_multiple_field():
    data = dict(city='Sofia', name='John Doe', salary=1e6)
    expected = dict(name='John Doe')

    serializer = MySerializer()
    serializer.drop_representation_fields(data, ('salary', 'city'))

    assert data == expected

You could add further test cases to verify scenarios like "raises keyerror when trying to drop missing field". Or you might decide to silently ignore missing fields and handle the KeyError exception in the mix-in class and implement test scenario "silently ignores missing field".