更新时间:2022-10-15 12:24:49
我没有线索,如果有一个更简单的方法,但我设法使这个工作的唯一方法是引用通过模型成员资格在组序列化程序中并编写.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')
对于validated_data中的项目:
如果Group._meta.get_field(item):
setattr(instance,item,validated_data [item])
Membership.objects.filter(group = instance).delete()
person_data中的person:
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:组1,
会员资格:[
{person:1},
{person:2}
]
}
I am trying to create a reference app in DRF 3 to demonstrate a nested serializer that can create/update models. The sample code below bombs with "*create() argument after ** must be a mapping, not list*" when trying to create the nested models. It is also no clear to me how I'd handle the .update() as in some cases I just want to be establish additional relationships (Persons).
The sample models:
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)
And the serializers and viewsets:
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()
I am trying to POST some JSON that inserts a Group with two (related) Persons:
{
"persons": [
{ "name" : "name 1" },
{ "name" : "name 2" }
],
"name": "group name 1"
}
I have no clue if there is an easier way, but the only way I managed to get this to work is to reference the 'through' model "memberships" in the Group serializer and write custom code for .create() and .update(). This seems like a lot of work to just set M2M FK's. If someone knows a better way I'd love to hear it.
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()
So you can create a new Group with related Person(s) using:
{
"name" : "Group 1",
"memberships" : [
{ "person" : 1 },
{ "person" : 2 }
]
}