django rest framework-如何展平嵌套数据? [英] django rest framework - how do you flatten nested data?

查看:96
本文介绍了django rest framework-如何展平嵌套数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个管理多对多关系的直通模型,并且我希望能够将直通模型和目标模型作为平面数据返回,而不是嵌套目标模型。

I have a 'through' model governing a many to many relationship and i want to be able to return the 'through' model and the target model as flat data, as opposed to having the target model nested.

因此,使用许多具有通孔的标准示例,说这些是模型,

So using the standard example for a many to many with a through, say these are the models,

class Person(models.Model):
    first_name = models.CharField(max_length=128)
    last_name = models.CharField(max_length=128)
    favourite_food = models.CharField(max_length=128)

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through='Membership')

class Membership(models.Model):
    person = models.ForeignKey(Person)
    group = models.ForeignKey(Group)
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)

因此序列化程序我现在要重演n成员资格项是

So the serializers i have at the moment to return Membership items are,

class MembershipSerializer(serializers.HyperlinkedModelSerializer):
    person = PersonSerializer()

    class Meta:
        model = Membership
        fields = ('id', 'url', 'group', 'date_joined', 'invite_reason', 'person')

class PersonSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Person
        fields = ('first_name', 'last_name', 'favourite_food')

因此,当我使用MembershipSerializer检索成员资格模型时,会得到此json,

So when i retrieve a Membership model using the MembershipSerializer, i get this json,

{
    'id':1,
    'url':'http://cheeselovers.com/api/member/1/'
    'group':'http://cheeselovers.com/api/group/1/'
    'date_joined': '2014-01-24T16:33:40.781Z',
    'invite_reason': 'loves cheese',
    'person':{
        'first_name':'Barry',
        'last_name':'CheeseLover',
        'favourite_food': 'cheese'
    }
}

但是我要返回的是这个,

but what i'd like returned is this,

{
    'id':1,
    'url':'http://cheeselovers.com/api/member/1/'
    'group':'http://cheeselovers.com/api/group/1/'
    'date_joined': '2014-01-24T16:33:40.781Z',
    'invite_reason': 'loves cheese',
    'first_name':'Barry',
    'last_name':'CheeseLover',
    'favourite_food': 'cheese'
}

现在,我意识到我可以简单地通过将MembershipSerializer更改为,

Now i realise that i could simply accomplish this by changing the MembershipSerializer to this,

class MembershipSerializer(serializers.HyperlinkedModelSerializer):
    first_name = serializers.Field(source='person.first_name')
    last_name = serializers.Field(source='person.last_name')
    favourite_food = serializers.Field(source='person.favourite_food')

    class Meta:
        model = Membership
        fields = ('id', 'url', 'group', 'date_joined', 'invite_reason', 'first_name', 'last_name', 'favourite_food')

但是,我拥有的目标模型具有10个属性,中介的直通模型仅具有只读道具,因此我已经有一个有效的目标模型序列化器,该序列化器在中介模型的创建过程中使用。

BUT, the target model i have has 10 properties and the intermediary 'through' model only has read only props, so i already have a functioning serializer for the target model, that's used during the creation of the intermediary model.

感觉可以重用,因此如果目标模型上的任何内容发生更改,我只需对其序列化程序进行更改,这些更改便会反映在数据中

It feels more DRY to be able to reuse this, so that if anything on the target model changes, i only have to make changes to it's serializer, for those changes to be then be reflected in the data returned by the intermediary's serializer.

那么有没有办法我可以从PersonSerializer中获取数据并将其添加到Membership数据中,以便它是平坦的而不是嵌套的?

So is there a way i can get the data from the PersonSerializer and add it to the Membership data, so that it's flat instead of nested?

...希望一切都有意义。

...hope that all makes sense.

推荐答案

I我不相信这是最简单的方法,但是我想出的解决方案是重写MembershipSerializer的to_native方法,然后手动创建并调用PersonSerializer的to_native方法并将两个结果字典合并在一起

I'm not convinced this is the simplest way, but the solution i came up with was to override the to_native method of the MembershipSerializer and then manually create and invoke the to_native method of the PersonSerializer and merge the two resulting dictionary's together

class MembershipSerializer(serializers.HyperlinkedModelSerializer):

    def to_native(self, obj):

        ret = super(MembershipSerializer, self).to_native(obj)
        p_serializer = PersonSerializer(obj.person, context=self.context)
        p_ret = p_serializer.to_native(obj.person)

        for key in p_ret:
            ret[key] = p_ret[key]

        return ret

    class Meta:
        model = Membership
        fields = ('id', 'url', 'group', 'date_joined', 'invite_reason', 'person')

字典都是SortedDict的子类。我不确定是否存在明确的方法来合并两个保留订单的方法,所以我只是使用了循环。

The dictionary's are both a subclass of SortedDict. I'm not sure whether there's an explicit method to merge the two that preserves the order, so i've just used a loop instead.

这篇关于django rest framework-如何展平嵌套数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆