簡體   English   中英

在 Django REST 框架中通過 Model 序列化多對多字段

[英]Serialize ManyToManyFields with a Through Model in Django REST Framework

through model 與此 M2M 關系為

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)

請注意,我在invite_reason中有額外的字段date_joined和邀請原因。

現在,我想使用 DRF 序列化Group查詢集,因此我選擇了下面的序列化程序設置。

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"
    }
]

這里的members字段返回Person信息,非常完美。

但,

如何將date_joinedinvite_reason字段/信息添加到 JSON 響應的members字段中?

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__"

筆記:

  • 覆蓋PersonSerializerto_representation(...)方法以將額外數據注入JSON 的members字段
  • 我們需要person instance/pk 和group instance/pk 來識別要序列化的Membership實例。 為此,我們使用了序列化器上下文來傳遞基本數據

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM