【问题标题】:Nested serializer "Through model" in Django Rest FrameworkDjango Rest Framework 中的嵌套序列化程序“通过模型”
【发布时间】:2019-01-16 10:43:30
【问题描述】:

我在序列化中间“枢轴”模型并附加到 Django Rest Framework 中多对多关系中的每个项目时遇到困难。

例子:

models.py:

class Member(models.Model):
    name = models.CharField(max_length = 20)
    groups = models.ManyToManyField('Group', through='Membership')

class Group(models.Model):
    name = models.CharField(max_length = 20)

class Membership(models.Model):
    member = models.ForeignKey('Member')
    group = models.ForeignKey('Group')
    join_date = models.DateTimeField()

serializers.py:

class MemberSerializer(ModelSerializer):
    class Meta:
        model = Member

class GroupSerializer(ModelSerializer):
    class Meta:
        model = Group

class MembershipSerializer(ModelSerializer):
    class Meta:
        model = Membership

我试图遵循答案: Include intermediary (through model) in responses in Django Rest Framework

但这并不是我所需要的

我需要生成以下输出

{
  "id": 1,
  "name": "Paul McCartney",
  "groups": [
    {
      "id": 3,
      "name": "Beatles",
      "membership": {
        "id": 2,
        "member_id": 1,
        "group_id": 3,
        "join_date": "2018-08-08T13:43:45-0300"
      }
    }
  ]
}

在此输出中,我为组中的每个项目返回相关的“通过模型”。

我怎样才能以这种方式生成序列化模型?

【问题讨论】:

    标签: python django django-rest-framework


    【解决方案1】:

    根据您希望显示输出的方式,我建议您将模型更改为:

    class Group(models.Model):
        name = models.CharField(max_length=20)
        members = models.ManyToManyField(
            'Membership',
            related_name='groups',
            related_query_name='groups',
        )
    
    
    class Member(models.Model):
        name = models.CharField(max_length=20)
    
    
    class Membership(models.Model):
        group = models.ForeignKey(
            'Group',
            related_name='membership',
            related_query_name='memberships',
        )
        join_date = models.DateTimeField()
    

    Group 模型和Member 模型是ManytoMany 的,没有问题你让Group 模型中的关系。在序列化中输出它是最容易的。 related_namerelated_query_name 用于进行序列化并指向嵌套关系。

    最后,你的序列化可能是这样的(我用 create 方法举例说明):

    class MembershipSerializer(ModelSerializer):
        class Meta:
            fields = ("id", "join_date",)
    
    
    class GroupSerializer(ModelSerializer):
        memberships = MembershipSerializer(many=True)
    
        class Meta:
            model = Group
            fields = ("id", "name", "memberships",)
    
    
    class MemberSerializer(ModelSerializer):
        groups = GroupSerializer(many=True)
    
        class Meta:
            model = Member
            fields = ("id", "name", "groups")
    
        def create(self):
            groups_data = validated_data.pop('groups')
            member = Member.objects.create(**validated_data)
            for group in groups_data:
                memberships_data = group.pop('memberships')
                Group.objects.create(member=member, **group)
                for memberhip in memberships:
                    Membership.objects.create(group=group, **memberships)
    

    输出将是:

    {
      "id": 1,
      "name": "Paul McCartney",
      "groups": [
        {
          "id": 3,
          "name": "Beatles",
          "memberships": [
            {
              "id": 2,
              "join_date": "2018-08-08T13:43:45-0300"
            }
          ]
        }
      ]
    }
    

    在此输出中,我没有“嵌套”父 ID,但您也可以这样做,只需在字段属性中声明即可。

    【讨论】:

    • 这会删除直通模型,因此不能完全回答问题。在这种情况下它可以工作,但是对于直通模型的用例可能需要序列化。
    【解决方案2】:

    通过查看您的输出,您似乎想要显示组内的成员资格和成员内的组。我建议将序列化程序编辑成这样。

    class MemberSerializer(ModelSerializer):
        groups = GroupSerializer(many=True)         
        class Meta:
            model = Member
            fields = ("id","name","groups")
    
    class GroupSerializer(ModelSerializer):
        membership = MembershipSerializer()        
        class Meta:
            model = Group
            fields = ("id","name","membership")
    
    class MembershipSerializer(ModelSerializer):
        class Meta:
            model = Membership
            fields = "__all__"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-20
      • 2019-06-02
      • 1970-01-01
      • 1970-01-01
      • 2016-02-09
      • 2018-07-06
      • 1970-01-01
      相关资源
      最近更新 更多