我尝试添加密钥serializer.data['test'] = 'asdf'
,但这似乎没有做任何事情。
我想转换键值的表示。为此,我尝试使用该值来计算新值并替换字典中的旧值。
这是我想要完成的,但我不知道为什么价值没有被取代。没有抛出错误,结果字典没有证据表明我试图替换任何东西:
class PlaceDetail(APIView):
def get(self, request, pk, format=None):
place = Place.objects.select_related().get(pk=pk)
serializer = PlaceSerializer(place)
#serializer.data['tags'] = pivot_tags(serializer.data['tags'])
serializer.data['test'] = 'asdf'
print(serializer.data['test'])
return Response(serializer.data)
终端:KeyError: 'test'
我通过打印观察到serializer.data
是一本字典。
我还测试了我尝试使用的语法应该有效:
>>> test = {'a': 'Alpha'}
>>> test
{'a': 'Alpha'}
>>> test['a']
'Alpha'
>>> test['a'] = 'asdf'
>>> test
{'a': 'asdf'}
如何正确修改serializer.data
字典?
答案 0 :(得分:11)
Serializer.data
属性返回使用OrderedDict
构建的serializer._data
。返回值本身不是serializer._data
。
因此,更改serializer.data
的返回值不会更改serializer._data
成员。因此,以下对serializer.data
的调用不会更改。
# 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)
您可以保留serializer.data
的返回值的副本,这是一个有序的字典,并根据需要进行操作。
实施例:
# 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)
为什么:
如果你看一下Django Restframework的源代码,你会在Serializer
类中看到,
Serializer._data
只是一个普通的字典。 Serializer.data
是一种装饰成属性的方法。它返回一个ReturnDict
对象,该对象是从OrderedDict
派生的自定义类。使用ReturnDict
中的键/值对初始化返回的Serializer._data
对象。如果Serializer.data
直接返回Serializer._data
,那么您的原始方法将按预期工作。但它不会起作用,因为它返回了另一个使用Serializer._data
构造的类字典对象。
请记住,Serializer.data
的返回值不是Serializer._data
,而是一个有序的字典对象。操纵返回值不会改变Serializer._data
。
我认为serializer.data
不直接返回serializer._data
的原因是为了避免意外更改数据并返回serializer._data
的漂亮表示。
答案 1 :(得分:0)
您需要使用SerializerMethodField,而不是明确覆盖表示。
答案 2 :(得分:0)
根据@yuwang的答案,我使用SerializerMethodField
来修改序列化程序中特定字段的值。这是一个示例:
我要修改的字段,我们称之为is_modifyable
。该字段在Django模型中以models.BooleanField
的形式出现,因此在序列化程序定义的字段列表中不存在,而在序列化程序定义下的class Meta:
定义中简单提及。
所以这是我的代码之前的样子:
# in models.py
# Model definition
class SomeModel(models.Model):
is_modifyable = models.BooleanField(default=True)
# in serializers.py
# Serializer definition
class SomeModelSerializer(serializers.ModelSerializer):
class Meta:
model = SomeModel
fields = ('is_modifyable',)
作为上述结果,总是根据is_modifyable
对象的记录中的值来获取字段SomeModel
的值。但是,出于某种测试目的,我希望在开发阶段将此字段的值返回为False,因此我将代码修改如下:
# in models.py
# Model definition (Left unchanged)
class SomeModel(models.Model):
is_modifyable = models.BooleanField(default=True)
# in serializers.py
# Serializer definition (This was updated)
class SomeModelSerializer(serializers.ModelSerializer):
# This line was added new
is_modifyable = serializers.SerializerMethodField(read_only=True)
class Meta:
model = SomeModel
fields = ('is_modifyable',)
# get_is_modifyable function was added new
def get_is_modifyable(self, obj) -> bool:
"""
Dummy method to always return False for test purpose
Returns: False
"""
return False
一旦输入了上述代码,API调用始终将序列化器字段is_modifyable
的值返回为False。