Python - Unable to modify the serializer.data dictionary in Django Rest Framework

The Serializer.data property returns an OrderedDict which is constructed using serializer._data. The return value is not serializer._data itself.

Thus changing the return value of serializer.data does not change serializer._data member. As a consequence, the following calls to serializer.data are not changed.

# In class Serializer(BaseSerializer)
@property
def data(self):
    ret = super(Serializer, self).data
    return ReturnDict(ret, serializer=self)

# In class ReturnDict(OrderedDict)
def __init__(self, *args, **kwargs):
    self.serializer = kwargs.pop('serializer')
    super(ReturnDict, self).__init__(*args, **kwargs)

You can keep a copy of the return value of serializer.data, which is an ordered dictionary, and manipulate it as you wish.

Example:

# keep the return value of serializer.data
serialized_data = serializer.data
# Manipulate it as you wish
serialized_data['test'] = 'I am cute'
# Return the manipulated dict
return Response(serialized_data)

Why:

If you look at the source code of Django Restframework, you will see that in Serializer class,

  • Serializer._data is just a normal dictionary.
  • Serializer.data is a method decorated to act like a property. It returns a ReturnDict object, which is a customized class derived from OrderedDict. The returned ReturnDict object is initialized using key/value pairs in Serializer._data.

If Serializer.data returns Serializer._data directly, then your original method will work as you expected. But it won't work since it's returning another dictionary-like object constructed using Serializer._data.

Just keep in mind that the return value of Serializer.data is not Serializer._data, but an ordered dictionary-like object. Manipulating the return value does not change Serializer._data.

I believe the reason why serializer.data does not return serializer._data directly is to avoid accidental change of the data and to return a pretty representation of serializer._data.