Python-无法修改Django Rest Fram中的serializer.data字典

2024-05-23 22:09:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图添加一个键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字典?


Tags: testalphadataget字典tagsplace形式
2条回答

您需要使用SerializerMethodField而不是显式地覆盖表示。

Serializer.data属性返回使用serializer._data构造的OrderedDict。返回值不是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的漂亮表示。

相关问题 更多 >