Django Rest Framework 中的嵌套序列化程序“通过模型”
Posted
技术标签:
【中文标题】Django Rest Framework 中的嵌套序列化程序“通过模型”【英文标题】:Nested serializer "Through model" in Django 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"
]
在此输出中,我为组中的每个项目返回相关的“通过模型”。
我怎样才能以这种方式生成序列化模型?
【问题讨论】:
【参考方案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_name
和related_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__"
【讨论】:
以上是关于Django Rest Framework 中的嵌套序列化程序“通过模型”的主要内容,如果未能解决你的问题,请参考以下文章
Django-rest-framework 中的全局异常处理
Django-Rest-Framework 中的序列化程序问题
如何从 django-rest-framework 中的文件列表中过滤图像
Django Rest Framework 中的 JWT 身份验证错误“无效签名”
django框架学习六:优化views.py文件,使用rest_framework中的APIVew和Response返回