Django 休息框架;如何使用外键的 ID 通过序列化程序创建实例?

时间:2021-03-29 17:09:23

标签: django django-rest-framework

我有两个序列化程序,一个用于 Country,一个用于我的模型 Foo,我想通过使用此模型的外键来保存对象,但是每当我尝试验证时都会出错。

我有这个

class Actor(TLPWrappedModel, CommentableModel):
    label = models.CharField(max_length=56, unique=True)
    country_of_origin = models.ForeignKey(Country, on_delete=models.CASCADE)



class FooSerializer(serializers.ModelSerializer):
    country_of_origin = CountrySerializer()

    class Meta:
        model = Actor
        fields = [
            'id',
            'country_of_origin',
            'label',
       ]


class Country(models.Model):
    label = models.CharField(max_length=56, unique=True)
    iso_code = models.CharField(max_length=3, unique=True)

class CountrySerializer(serializers.ModelSerializer):
    class Meta:
        model = Country
        fields = [
            'iso_code',
            'label',
        ]

这就是我想要做的

    serializers = FooSerializer(data={'label': 'Foobar',
                                        'country_of_origin': self.country.id})
    serializers.is_valid()
    print(serializers.errors)
    print(serializers.validated_data)
    serializers.save()

但我收到此错误 {'country_of_origin': {'non_field_errors': [ErrorDetail(string='Invalid data. Expected a dictionary, but got int.', code='invalid')]}}

是否可以使用外键的 ID 来验证和使用序列化程序创建对象?

3 个答案:

答案 0 :(得分:1)

试试

class FooSerializer(serializers.ModelSerializer):
    

    class Meta:
        model = Actor
        fields = [
            'id',
            'country_of_origin',
            'label',
       ]

您可以安全地删除在 FooSerializer 中定义“原产国”

答案 1 :(得分:1)

contry_of_origin 将是一个对象,您正在为它传递一个 id。

你需要一个嵌套的序列化器吗? : country_of_origin = CountrySerializer() 对于您给出的示例,我建议您将其更改为 PrimaryKeyRelatedField()

您的序列化程序看起来像:

class FooSerializer(serializers.ModelSerializer):
    country_of_origin = serializers.PrimaryKeyRelatedField()

    class Meta:
        model = Actor
        fields = [
            'id',
            'country_of_origin',
            'label',
       ]

答案 2 :(得分:1)

我们可以更新 FooSerializer 的 to_represent 以获得所需的输出

试试

class FooSerializer(serializers.ModelSerializer):

    class Meta:
        model = Actor
        fields = [
            'id',
            'country_of_origin',
            'label',
       ]
    
    def to_representation(self, instance):
        data = super().to_representation(instance)
        data['country_of_origin'] = CountrySerializer(instance.country_of_origin)
        return data

 serializers = FooSerializer(data={'label': 'Foobar', 'country_of_origin': self.country})
 serializers.is_valid(raise_expection=True)
 serializers.save()

在这里,我更新了代码以将 self.country 分配为 country_of_origin。另外,我在 raise_expection 方法中使用了 is_valid。此方法将错误作为 400 响应返回。