django-restframework将关系序列化为字典而不是数组

时间:2017-07-21 10:58:11

标签: python json django django-rest-framework

我试图将外键序列化为字典而不是数组。 现在json看起来如下:

{
"slug": "en",
"children": [{
        "slug": "pants",
        "children": [{
                "slug": "products/:level1",
                "children": [{
                    "slug": ":level2/:level3",
                    "children": []
                }]
            },
            {
                "slug": ":productSlug",
                "children": []
            }
        ]
    },
    {
        "slug": "pullovers",
        "children": []
    }
   ]
}

但是我喜欢用slugs作为键:

{
"en": {
    "children": {
        "pants": {
            "children": {
                "products/:level1": {
                    "children": {
                        ":level2/:level3": {
                            "children": {}
                        }
                    }
                }
            },
            ":productSlug": {
                "children": {}
            }
        ]
    }
 }
}

是否可以直接在序列化程序中执行此操作,还是必须在另外的步骤中进行转换?

2 个答案:

答案 0 :(得分:1)

可以通过覆盖list serializers并为每个需要它的序列化程序设置list_serializer_class,就像我在answer中所建议的那样。

当然,您需要稍微调整一下:

class <YourClass>ListSerializer(serializers.ListSerializer):
    def to_representation(self, data):
        r = super().to_representation(data)

        return { item['<key_field>']: item for item in r }

答案 1 :(得分:1)

@Michael Rigonis回答(https://stackoverflow.com/a/45238191/270265)是成功的关键。我不得不稍微调整一下,所以我也可以将它用于顶层:

class DictSerializer(serializers.ListSerializer):
    key = None

    def __init__(self, *args, **kwargs):
        self.key = kwargs.pop('key', self.key)
        super().__init__(*args, **kwargs)

    def to_representation(self, data):    
        r = super().to_representation(data)
        return {item[self.key]: item for item in r}

    @property
    def data(self):
        # This is a bit nasty, because the only "Many-Serializer" is a ListSerializer we inherit of it,
        # but when converting it to json we call the BaseSerializer directly, because we want a Dictionary rather then a list
        ret = super(serializers.ListSerializer, self).data
        return ReturnDict(ret, serializer=self)