在Django REST Framework中使用直通模型序列化ManyToManyFields [英] Serialize ManyToManyFields with a Through Model in Django REST Framework

查看:28
本文介绍了在Django REST Framework中使用直通模型序列化ManyToManyFields的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我与通过模型的这种M2M关系为

I have this M2M relation with through model as

class Person(models.Model):
    name = models.CharField(max_length=128)

    def __str__(self):
        return self.name


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

    def __str__(self):
        return self.name


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

请注意,直通模型中有 date_joined invite_reason 额外的字段.

Please note that, I have extra fields date_joined and invite_reason in the through model.

现在,我想使用DRF序列化 Group 查询集,因此我选择了以下序列化程序设置.

Now, I want to serialize the Group queryset using DRF and thus I choose the below serializer setup.

class PersonSerializer(serializers.ModelSerializer):
    class Meta:
        model = Person
        fields = "__all__"


class GroupSerializer(serializers.ModelSerializer):
    members = PersonSerializer(read_only=True, many=True)

    class Meta:
        model = Group
        fields = "__all__"

,它返回以下响应,

[
    {
        "id": 1,
        "members": [
            {
                "id": 1,
                "name": "Jerin"
            }
        ],
        "name": "Developer"
    },
    {
        "id": 2,
        "members": [
            {
                "id": 1,
                "name": "Jerin"
            }
        ],
        "name": "Team Lead"
    }
]

在此, 成员 字段返回 Person 信息,这很完美.

Here, the members field returning the Person information, which is perfect.

但是

如何将 date_joined invite_reason 字段/信息添加到JSON响应的 members 字段中?>

How can I add the date_joined and invite_reason field/info into the members field of the JSON response?

推荐答案

class PersonSerializer(serializers.ModelSerializer):
    class Meta:
        model = Person
        fields = "__all__"

    def serialize_membership(self, person_instance):
        # simple method to serialize the through model fields
        membership_instance = person_instance \
            .membership_set \
            .filter(group=self.context["group_instance"]) \
            .first()

        if membership_instance:
            return MembershipSerializer(membership_instance).data
        return {}

    def to_representation(self, instance):
        rep = super().to_representation(instance)
        return {**rep, **self.serialize_membership(instance)}


class MembershipSerializer(serializers.ModelSerializer): # create new serializer to serialize the through model fields
    class Meta:
        model = Membership
        fields = ("date_joined", "invite_reason")


class GroupSerializer(serializers.ModelSerializer):
    members = serializers.SerializerMethodField() # use `SerializerMethodField`, can be used to pass context data 

    def get_members(self, group):
        return PersonSerializer(
            group.members.all(),
            many=True,
            context={"group_instance": group}  # should pass this `group` instance as context variable for filtering
        ).data

    class Meta:
        model = Group
        fields = "__all__"

注意:

  • 覆盖 PersonSerializer to_representation(...) 方法,以将多余的数据注入成员字段
  • 我们需要 person 实例/pk和 group 实例/pk来标识要序列化的 Membership 实例.为此,我们使用了 serializer上下文传递基本数据
  • Override the to_representation(...) method of PersonSerializer to inject extra data into the members field of the JSON
  • We need person instance/pk and group instance/pk to identify the Membership instance to be serialized. For that, we have used the serializer context to pass essential data

这篇关于在Django REST Framework中使用直通模型序列化ManyToManyFields的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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