我正在使用自定义ListSerializer重新格式化JSON响应,当我从序列化程序内部进行日志记录时,它会生成正确的格式,但是当它返回到ViewSet时,响应将成为字典键的列表,而不是包括包含键和值的整个字典。
我用硬编码的JSON做了一个简化的例子来说明我认为是问题的症结所在。
views.py
class ElementViewSet(viewsets.ViewSet):
...
@detail_route(methods=['get'])
def elements(self, request, pk=None):
elements = ElementFilterSet(params)
serializer = serializers.ElementSerializer(elements, many=True)
return Response(serializer.data)
serializers.py
class ElementListSerializer(serializers.ListSerializer):
def to_representation(self, obj):
result = {"home": {"label_color": "#123456","label_text": "young"},"speak": { "label_color": "","label_text": "Hello"}}
return result
class ElementSerializer(serializers.ModelSerializer):
class Meta:
model = Element
list_serializer_class = ElementListSerializer
def to_representation(self, obj):
result = super(ElementSerializer, self).to_representation(obj)
return result
我得到的回复是字典键列表:
[
"speak",
"home"
]
而不是我想要的,这是整个字典(在这种情况下,只是硬编码的JSON result
):
{
"home": {
"label_color": "#123456",
"label_text": "young"
},
"speak": {
"label_color": "",
"label_text": "Hello"
}
}
我不熟悉自定义序列化程序并使用list_serializer_class
;我可能根本就不明白它们是如何工作的,但这种行为对我来说确实是出乎意料的。
答案 0 :(得分:1)
根据文档定义:ListSerializer类提供一次序列化和验证多个对象的行为。 如果您传递的数据可以表示为序列化数据,那么您通常不需要ListSerializers。 建议的解决方案是使用嵌套的序列化程序,如果您没有从模型实例获取键值:
class ElementListSerializer(serializers.BaseSerializer):
def to_representation(self, obj):
return {
'home': {"label_color": "#123456",
"label_text": "young"},
'speak': {
"label_color": "",
"label_text": "Hello"}
}
class ElementSerializer(serializers.ModelSerializer):
element_list = ElementListSerializer()
class Meta:
model = Element
def create(self, validated_data):
data = validated_data.pop('element_list')
return data
答案 1 :(得分:0)
问题出在ListSerializer的属性data
上,该属性返回ReturnList而不是ReturnDict。
要修复代码,必须更改data
属性:
from rest_framework import serializers
class ElementListSerializer(serializers.ListSerializer):
def to_representation(self, obj):
result = {"home": {"label_color": "#123456","label_text": "young"},"speak": { "label_color": "","label_text": "Hello"}}
return result
@property
def data(self):
ret = serializers.BaseSerializer.data.fget(self)
return serializers.ReturnDict(ret, serializer=self)
class ElementSerializer(serializers.ModelSerializer):
class Meta:
model = Element
list_serializer_class = ElementListSerializer
def to_representation(self, obj):
result = super(ElementSerializer, self).to_representation(obj)
return result
您还可以创建一个通用解决方案。它将自动将具有相同结构的字典列表转换为一个字典,其中键将来自子字典的指定字段。
class ListToDictSerializer(serializers.ListSerializer):
def to_representation(self, data):
return {
item[self.child.Meta.dict_serializer_key]: self.child.to_representation(item)
for item in data
}
@property
def data(self):
ret = drf_serializers.BaseSerializer.data.fget(self)
return serializers.ReturnDict(ret, serializer=self)
class MyModelSerializer(serializers.ModelSerializer):
class Meta:
model = Model
list_serializer_class = ListToDictSerializer
dict_serializer_key = 'id'