DRF 3 - 使用 though table 创建多对多 update/create 序列化程序
DRF 3 - Creating Many-to-Many update/create serializer with though table
我正在尝试在 DRF 3 中创建一个参考应用程序来演示可以 create/update 建模的嵌套序列化程序。在尝试创建嵌套模型时,下面的示例代码用“*create() argument after ** must be a mapping, not list*”轰炸。我也不清楚我将如何处理 .update() 因为在某些情况下我只想建立额外的关系(人)。
样本模型:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
persons = models.ManyToManyField(Person, through='Membership')
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
以及序列化程序和视图集:
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from app.models import Group, Person
class PersonSerializer(ModelSerializer):
class Meta:
model = Person
class GroupSerializer(ModelSerializer):
persons = PersonSerializer(many=True)
def create(self, validated_data):
persons = validated_data.pop('persons')
group = Group.objects.create(**validated_data)
if persons: # Bombs without this check
Person.objects.create(group=group, **persons) # Errors here
return group
class Meta:
model = Group
class PersonModelViewSet(ModelViewSet):
serializer_class = PersonSerializer
queryset = Person.objects.all()
class GroupModelViewSet(ModelViewSet):
serializer_class = GroupSerializer
queryset = Group.objects.all()
我正在尝试 POST 一些 JSON 插入一个有两个(相关)人的组:
{
"persons": [
{ "name" : "name 1" },
{ "name" : "name 2" }
],
"name": "group name 1"
}
使用此处显示的 PrimaryKeyRelatedField
:
http://www.django-rest-framework.org/api-guide/relations/#primarykeyrelatedfield
class GroupSerializer(serializers.ModelSerializer):
persons = serializers.PrimaryKeyRelatedField(
many=True, queryset=Person.objects.all())
class Meta:
model = Group
fields = ('name', 'persons')
例如,首先创建每个人。 ID 为 1 的人,姓名 = "Bob"。 ID 为 2 的人,姓名 = "Tim"。然后 post 他们使用他们的 primary keys
到 REST 端点 所以:
# Group create() REST endpoint data to POST
{'name': 'my group', 'persons': [1, 2]}
现在您之前创建的人是该组的一部分。
我不知道是否有更简单的方法,但我设法让它工作的唯一方法是在组序列化程序中引用 'through' 模型 "memberships" 并编写自定义代码对于 .create() 和 .update()。这似乎只是设置 M2M FK 的大量工作。如果有人知道更好的方法,我很乐意听到。
class GroupMembershipSerializer(ModelSerializer):
class Meta:
model = Membership
fields = ('person',)
class GroupCreateSerializer(ModelSerializer):
memberships = GroupMembershipSerializer(many=True, required=False)
def create(self, validated_data):
person_data = validated_data.pop('memberships')
group = Group.objects.create(**validated_data)
for person in person_data:
d=dict(person)
Membership.objects.create(group=group, person=d['person'])
return group
def update(self, instance, validated_data):
person_data = validated_data.pop('memberships')
for item in validated_data:
if Group._meta.get_field(item):
setattr(instance, item, validated_data[item])
Membership.objects.filter(group=instance).delete()
for person in person_data:
d=dict(person)
Membership.objects.create(group=instance, person=d['person'])
instance.save()
return instance
class Meta:
model = Group
class GroupCreateModelViewSet(ModelViewSet):
serializer_class = GroupCreateSerializer
queryset = Group.objects.all()
因此您可以使用相关人员创建一个新组:
{
"name" : "Group 1",
"memberships" : [
{ "person" : 1 },
{ "person" : 2 }
]
}
我正在尝试在 DRF 3 中创建一个参考应用程序来演示可以 create/update 建模的嵌套序列化程序。在尝试创建嵌套模型时,下面的示例代码用“*create() argument after ** must be a mapping, not list*”轰炸。我也不清楚我将如何处理 .update() 因为在某些情况下我只想建立额外的关系(人)。
样本模型:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
persons = models.ManyToManyField(Person, through='Membership')
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
以及序列化程序和视图集:
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from app.models import Group, Person
class PersonSerializer(ModelSerializer):
class Meta:
model = Person
class GroupSerializer(ModelSerializer):
persons = PersonSerializer(many=True)
def create(self, validated_data):
persons = validated_data.pop('persons')
group = Group.objects.create(**validated_data)
if persons: # Bombs without this check
Person.objects.create(group=group, **persons) # Errors here
return group
class Meta:
model = Group
class PersonModelViewSet(ModelViewSet):
serializer_class = PersonSerializer
queryset = Person.objects.all()
class GroupModelViewSet(ModelViewSet):
serializer_class = GroupSerializer
queryset = Group.objects.all()
我正在尝试 POST 一些 JSON 插入一个有两个(相关)人的组:
{
"persons": [
{ "name" : "name 1" },
{ "name" : "name 2" }
],
"name": "group name 1"
}
使用此处显示的 PrimaryKeyRelatedField
:
http://www.django-rest-framework.org/api-guide/relations/#primarykeyrelatedfield
class GroupSerializer(serializers.ModelSerializer):
persons = serializers.PrimaryKeyRelatedField(
many=True, queryset=Person.objects.all())
class Meta:
model = Group
fields = ('name', 'persons')
例如,首先创建每个人。 ID 为 1 的人,姓名 = "Bob"。 ID 为 2 的人,姓名 = "Tim"。然后 post 他们使用他们的 primary keys
到 REST 端点 所以:
# Group create() REST endpoint data to POST
{'name': 'my group', 'persons': [1, 2]}
现在您之前创建的人是该组的一部分。
我不知道是否有更简单的方法,但我设法让它工作的唯一方法是在组序列化程序中引用 'through' 模型 "memberships" 并编写自定义代码对于 .create() 和 .update()。这似乎只是设置 M2M FK 的大量工作。如果有人知道更好的方法,我很乐意听到。
class GroupMembershipSerializer(ModelSerializer):
class Meta:
model = Membership
fields = ('person',)
class GroupCreateSerializer(ModelSerializer):
memberships = GroupMembershipSerializer(many=True, required=False)
def create(self, validated_data):
person_data = validated_data.pop('memberships')
group = Group.objects.create(**validated_data)
for person in person_data:
d=dict(person)
Membership.objects.create(group=group, person=d['person'])
return group
def update(self, instance, validated_data):
person_data = validated_data.pop('memberships')
for item in validated_data:
if Group._meta.get_field(item):
setattr(instance, item, validated_data[item])
Membership.objects.filter(group=instance).delete()
for person in person_data:
d=dict(person)
Membership.objects.create(group=instance, person=d['person'])
instance.save()
return instance
class Meta:
model = Group
class GroupCreateModelViewSet(ModelViewSet):
serializer_class = GroupCreateSerializer
queryset = Group.objects.all()
因此您可以使用相关人员创建一个新组:
{
"name" : "Group 1",
"memberships" : [
{ "person" : 1 },
{ "person" : 2 }
]
}