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 aReturnDict
object, which is a customized class derived fromOrderedDict
. The returnedReturnDict
object is initialized using key/value pairs inSerializer._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
.