在Django Rest Framework中更改序列化对象的结构(在模型内容之外拉取ID字段)

时间:2015-11-29 03:28:31

标签: json serialization django-rest-framework

比如说,你有一个带有名称和电子邮件的模型,并使用Model Serializer通过Django Rest Framework序列化你的数据。输出将是这样的:

[{
    "id": "1",
    "name": "Alex",
    "email": "alex@host.com"
}, {
    "id": "2",
    "name": "Henry",
    "email": "henry@host.com"
}]

有没有办法在模型内容的其余部分之外“拉”一个唯一字段来获取它?:

{
    "1": {
        "name": "Alex",
        "email": "alex@host.com"
    },
    "2": {
        "name": "Henry",
        "email": "henry@host.com"
    }
}

我能够通过重写序列化程序的to_representation()方法(下面的代码示例)来“外化”ID,但我无法摆脱基本的包装器 - 目前JRF将返回所有内容list[] dict(instance)与此类似:

data = list
for item in instance:
    list.append(item.as_dict())

我不需要这是list的{​​{1}},我希望他们做dict的词典吗?

dicts

这是我的to_representation()代码,我只能操作为单个实例返回的内容,所以它必须是一个dict,但我需要合并这个dict,而不是在serializer.data完全煮熟时在输出处堆叠

data = {}
for item in instance:
    data[item.id] = item.as_dict()

我能够通过重新格式化原始的串行器输出来使其工作,但它肯定不是一个具有很大性能影响的干净解决方案:

def to_representation(self, instance):
    rep = OrderedDict()
    fields = self._readable_fields
    id_field = filter(lambda i: i.label == "ID", fields)[0]
    if id_field:
        id_atr = id_field.get_attribute(instance).__str__()
    else:
        raise Exception('cannot serialize models without ID field')
    rep[id_atr] = {}
    for field in fields:
        try:
            attribute = field.get_attribute(instance)
        except SkipField:
            continue
        if attribute is None:
            rep[id_atr][field.field_name] = None
        else:
            rep[id_atr][field.field_name] = field.to_representation(attribute)
    return rep

根据@ zaphod100-10回答,我创建了一个自定义的ListSerializer类:

def list(self, request, *args, **kwargs):
    _data = super(ChatMessageViewSet, self).list(request, *args, **kwargs)
    _resp = {}
    for item in _data.data:
        _id = item.get('id', None)
        if not _id:
            raise Exception('cannot serialize data without id field')
        _resp[_id] = {}
        for element in item:
            _resp[_id][element] = item[element]
    _data.data = _resp
    return _data

它以我需要的方式格式化数据: debug view screenshot

但是我的数据不能在“ListModelMixin”中存活:

class ChatMessageListSerializer(serializers.ListSerializer):

    def to_representation(self, data):

        iterable = data.all() if isinstance(data, models.Manager) else data
        _data = {}
        for item in iterable:
            _data[item.id] = self.child.to_representation(item)
        return _data

它只返回实体ID的列表[]:serializer = self.get_serializer(queryset, many=True) return Response(serializer.data)

1 个答案:

答案 0 :(得分:2)

为您的模型创建自定义ListSerializer并覆盖to_representation方法。

def to_representation(self, data):
    # convert your data which is a queryset or a 
    # list of objects to dict of dicts
    .....
    return dict_of_dicts

在主序列化程序类中创建ListSerializer后,添加list_serializer_class元属性。

在此处阅读有关列表序列化程序的更多信息:

http://www.django-rest-framework.org/api-guide/serializers/#listserializer