Return 对象列表作为字典,键作为对象 id 与 django rest framerwork
Return list of objects as dictionary with keys as the objects id with django rest framerwork
目前,我有一个 ListAPIView returns 一个对象字典列表:
[
{ id: 1, ...},
{ id: 2, ...},
...
]
我想将其更改为以 id 为键的字典格式:
{
"1": { id: 1, ...},
"2": { id: 2, ...},
...
}
如何使用 Django Rest Framework 以这种方式自定义输出?目前我正在重新格式化客户端,但我想在服务器端进行。
您可以遍历每个项目,并通过字典理解创建您想要的字典。例如:
>>> l = [{ "id": 1, "x": 4}, { "id": 2, "x": 3}]
>>> {v["id"]: v for v in l}
{1: {'x': 4, 'id': 1}, 2: {'x': 3, 'id': 2}}
我认为你可以在序列化程序中实现 to_representation
功能。
class MySerializer(serializers.Serializer):
id = serializers.ReadOnlyField()
field1 = serializers.ReadOnlyField()
field2 = serializers.ReadOnlyField()
def to_representation(self, data):
res = super(MySerializer, self).to_representation(data)
return {res['id']: res}
# or you can fetch the id by data directly
# return {str(data.id): res}
编辑:当前版本在 Github project 和 PYPI (pip install drf-keyed-list
)
中可用
这是一个双向的通用 class(相对于上面的只读实现):
class KeyedListSerializer(ListSerializer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
meta = getattr(self.child, 'Meta', None)
assert hasattr(meta, 'keyed_list_serializer_field'), \
"Must provide a field name at keyed_list_serializer_field when using KeyedListSerializer"
self._keyed_field = meta.keyed_list_serializer_field
def to_internal_value(self, data):
# syntax is py3 only
data = [{**v, **{self._keyed_field: k}} for k, v in data.items()]
return super().to_internal_value(data)
def to_representation(self, data):
response = super().to_representation(data)
return {v.pop(self._keyed_field): v for v response}
对于 Py2,您需要显式调用 super
并替换指示的字典构造函数。您可以通过将它分配给您的 list_serializer_class
并选择一个 keyed_list_serializer_field
(即用作字典键的字段)来使用它:
class MySerializer(ModelSerializer):
class Meta:
list_serializer_class = KeyedListSerializer
keyed_list_serializer_field = 'id'
keyed_list_serializer_field
应包含唯一值;上面的实现没有检查。
目前,我有一个 ListAPIView returns 一个对象字典列表:
[
{ id: 1, ...},
{ id: 2, ...},
...
]
我想将其更改为以 id 为键的字典格式:
{
"1": { id: 1, ...},
"2": { id: 2, ...},
...
}
如何使用 Django Rest Framework 以这种方式自定义输出?目前我正在重新格式化客户端,但我想在服务器端进行。
您可以遍历每个项目,并通过字典理解创建您想要的字典。例如:
>>> l = [{ "id": 1, "x": 4}, { "id": 2, "x": 3}]
>>> {v["id"]: v for v in l}
{1: {'x': 4, 'id': 1}, 2: {'x': 3, 'id': 2}}
我认为你可以在序列化程序中实现 to_representation
功能。
class MySerializer(serializers.Serializer):
id = serializers.ReadOnlyField()
field1 = serializers.ReadOnlyField()
field2 = serializers.ReadOnlyField()
def to_representation(self, data):
res = super(MySerializer, self).to_representation(data)
return {res['id']: res}
# or you can fetch the id by data directly
# return {str(data.id): res}
编辑:当前版本在 Github project 和 PYPI (pip install drf-keyed-list
)
这是一个双向的通用 class(相对于上面的只读实现):
class KeyedListSerializer(ListSerializer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
meta = getattr(self.child, 'Meta', None)
assert hasattr(meta, 'keyed_list_serializer_field'), \
"Must provide a field name at keyed_list_serializer_field when using KeyedListSerializer"
self._keyed_field = meta.keyed_list_serializer_field
def to_internal_value(self, data):
# syntax is py3 only
data = [{**v, **{self._keyed_field: k}} for k, v in data.items()]
return super().to_internal_value(data)
def to_representation(self, data):
response = super().to_representation(data)
return {v.pop(self._keyed_field): v for v response}
对于 Py2,您需要显式调用 super
并替换指示的字典构造函数。您可以通过将它分配给您的 list_serializer_class
并选择一个 keyed_list_serializer_field
(即用作字典键的字段)来使用它:
class MySerializer(ModelSerializer):
class Meta:
list_serializer_class = KeyedListSerializer
keyed_list_serializer_field = 'id'
keyed_list_serializer_field
应包含唯一值;上面的实现没有检查。