在Django REST框架中使用ModelSerializer创建关联数据

在Django REST框架中使用ModelSerializer创建关联数据,django,django-rest-framework,Django,Django Rest Framework,我正在使用Django 2.0和Django REST框架来编写RESTAPI My联系人/型号.py包含 class Contact(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) first_name = models.CharField(max_length=100) last_name = models.CharField(max_length=100, blank=T

我正在使用
Django 2.0
Django REST框架
来编写RESTAPI

My联系人/型号.py包含

class Contact(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100, blank=True, null=True)
    date_of_birth = models.DateField(blank=True, null=True)
    avatar = models.ImageField(upload_to='contact/%Y/%m/%d', blank=True)

    class Meta:
        db_table = 'contacts'


class ContactPhoneNumber(models.Model):
    contact = models.ForeignKey(Contact, on_delete=models.CASCADE)
    phone = models.CharField(max_length=100)

    class Meta:
        db_table = 'contact_phone_numbers'
联系人/序列化程序.py

class ContactPhoneNumberSerializer(serializers.ModelSerializer):
    class Meta:
        model = ContactPhoneNumber
        fields = ('id', 'phone', 'primary', 'created', 'modified')


class ContactSerializer(serializers.HyperlinkedModelSerializer):
    phone_numbers = ContactPhoneNumberSerializer(source='contactphonenumber_set', many=True)
    url = serializers.HyperlinkedRelatedField(
        view_name='contacts:detail',
        read_only=True
    )

    class Meta:
        model = Contact
        fields = ('url', 'id', 'first_name', 'last_name', 'date_of_birth', 'avatar', 'phone_numbers')


    def create(self, validated_data):
        print(validated_data)
        instance = Contact.objects.create(**validated_data)
        instance.save()
        return instance
我希望能够创建
联系人
以及
电话号码
,并且一个联系人可以有多个电话号码

但当我只发送带有联系人数据的POST请求时,它会给出如下错误:

'contactphonenumber_set' is an invalid keyword argument for this function
仅在呼叫联系人时,在json响应中显示所有关联的手机号码,但无法创建记录

打印(验证数据)
提供以下数据

{'first_name': 'Anshuman', 'last_name': 'Upadhyay', 'date_of_birth': datetime.date(2018, 5, 15), 'contactphonenumber_set': [], 'user_id': <SimpleLazyObject: <User: anuj>>}
{'first_name':'Anshuman','last_name':'Upadhyay','date_出生日期]:datetime.date(2018,5,15),'contactphonenumber_set':[],'user_id':}

如何使用REST Framework创建相关的多个字段?

您不能将
contactphonenumber\u set
传递给
对象。create()
方法直接传递。您应该分别创建每个相关的电话号码,如下所示:

def create(self, validated_data):
        print(validated_data)
        phone_numbers = validated_data.pop('contactphonenumber_set')
        instance = Contact.objects.create(**validated_data)
        for phone_data in phone_numbers:
            ContactPhoneNumber.objects.create(contact=instance, **phone_data)
        return instance

请参阅有关可写嵌套序列化程序的详细信息。

您不能将
contactphonenumber\u set
传递给
对象。create()
方法直接传递。您应该分别创建每个相关的电话号码,如下所示:

def create(self, validated_data):
        print(validated_data)
        phone_numbers = validated_data.pop('contactphonenumber_set')
        instance = Contact.objects.create(**validated_data)
        for phone_data in phone_numbers:
            ContactPhoneNumber.objects.create(contact=instance, **phone_data)
        return instance
请参阅有关可写嵌套序列化程序的详细信息。

为您演示

models.py:

class UnitGroup(models.Model):
    name = models.CharField(max_length=255,
                            verbose_name='名称')

class Unit(models.Model):
    unit_group = models.ForeignKey('medicine.UnitGroup',
                                   related_name='unit_unit_group',
                                   null=True,
                                   on_delete=models.SET_NULL,
                                   verbose_name='unit_group')
    name = models.CharField(max_length=255,
                            verbose_name='name')
    display_name = models.CharField(max_length=255,
                                    verbose_name='display_name')
serializers.py:

class UnitCreateSerializer(ModelSerializer):
    class Meta:
        model = Unit
        fields = ('name', 'display_name', 'ratio', 'is_active')

class UnitGroupCreateSerializer(WritableNestedModelSerializer):
    unit_unit_group = UnitCreateSerializer(many=True)

    class Meta:
        model = UnitGroup
        fields = ('unit_unit_group', 'name')
tests.py:

class UnitGroupTests(APITestCase):
    def setUp(self):
        try:
            self.user = User.objects.get(tel='18094213198')
        except User.DoesNotExist:
            self.user = User.objects.create_user(tel='18094213198', password='123456')
        self.user.user_permissions.add(*get_model_permission(UnitGroup))
        token, _ = Token.objects.get_or_create(user=self.user)
        self.access_token = token.access_token

    def test_create(self):
        """create"""
        url = reverse('unitgroup-list')
        self.client.credentials(HTTP_AUTHORIZATION='Token ' + self.access_token)
        data = {'name': 'Widget', 'unit_unit_group': [{'name': '1', 'display_name': 'yi'}]}
        response = self.client.post(url, data, format='json')
        print([(x, x.unit_group) for x in Unit.objects.all()])
        print('create', json.dumps(response.data, ensure_ascii=False, indent=2))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
测试输出:

[(<Unit: 1>, <UnitGroup: Widget>)]
create{
  "id": 1,
  "name": "Widget",
  "create_time": "2018-05-08 16:59:51",
  "update_time": "2018-05-08 16:59:51"
}
[(,)]
创造{
“id”:1,
“名称”:“小部件”,
“创建时间”:“2018-05-08 16:59:51”,
“更新时间”:“2018-05-08 16:59:51”
}
为您演示

models.py:

class UnitGroup(models.Model):
    name = models.CharField(max_length=255,
                            verbose_name='名称')

class Unit(models.Model):
    unit_group = models.ForeignKey('medicine.UnitGroup',
                                   related_name='unit_unit_group',
                                   null=True,
                                   on_delete=models.SET_NULL,
                                   verbose_name='unit_group')
    name = models.CharField(max_length=255,
                            verbose_name='name')
    display_name = models.CharField(max_length=255,
                                    verbose_name='display_name')
serializers.py:

class UnitCreateSerializer(ModelSerializer):
    class Meta:
        model = Unit
        fields = ('name', 'display_name', 'ratio', 'is_active')

class UnitGroupCreateSerializer(WritableNestedModelSerializer):
    unit_unit_group = UnitCreateSerializer(many=True)

    class Meta:
        model = UnitGroup
        fields = ('unit_unit_group', 'name')
tests.py:

class UnitGroupTests(APITestCase):
    def setUp(self):
        try:
            self.user = User.objects.get(tel='18094213198')
        except User.DoesNotExist:
            self.user = User.objects.create_user(tel='18094213198', password='123456')
        self.user.user_permissions.add(*get_model_permission(UnitGroup))
        token, _ = Token.objects.get_or_create(user=self.user)
        self.access_token = token.access_token

    def test_create(self):
        """create"""
        url = reverse('unitgroup-list')
        self.client.credentials(HTTP_AUTHORIZATION='Token ' + self.access_token)
        data = {'name': 'Widget', 'unit_unit_group': [{'name': '1', 'display_name': 'yi'}]}
        response = self.client.post(url, data, format='json')
        print([(x, x.unit_group) for x in Unit.objects.all()])
        print('create', json.dumps(response.data, ensure_ascii=False, indent=2))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
测试输出:

[(<Unit: 1>, <UnitGroup: Widget>)]
create{
  "id": 1,
  "name": "Widget",
  "create_time": "2018-05-08 16:59:51",
  "update_time": "2018-05-08 16:59:51"
}
[(,)]
创造{
“id”:1,
“名称”:“小部件”,
“创建时间”:“2018-05-08 16:59:51”,
“更新时间”:“2018-05-08 16:59:51”
}