嵌套可写序列化程序上的验证错误

Posted

技术标签:

【中文标题】嵌套可写序列化程序上的验证错误【英文标题】:Validation error on nested writable serializer 【发布时间】:2022-01-22 16:00:20 【问题描述】:

我有一个像这样的可写嵌套序列化器 -

class AddressSerializer(serializers.ModelSerializer):
    class Meta:
        model = publicAddress
        fields = "__all__"


class customerSerializer(serializers.ModelSerializer):
    publicAdd = AddressSerializer(many=True)
        class Meta:
        model = customerMaster
        fields = ['id','publicAdd']

    def create(self, validated_data):
        Address = validated_data.pop('publicAdd')
        customer = customerMaster.objects.create(**validated_data)
        for addres in Address:
            publicAddress.objects.create(customer=customer, **addres)
        return customer

这一切正常,直到我应用验证,例如

class AddressSerializer(serializers.ModelSerializer):
    class Meta:
        model = publicAddress
        fields = "__all__"
        validators = [
            UniqueTogetherValidator(
                queryset=publicAddress.objects.all(),
                fields=['customer', 'someValue']
            )
        ]

定义

read_only_fields = ('customer',)

在 AddressSerializer 中也无济于事。

现在它会抛出一个错误,例如 cust 字段始终是必需的,并通过 api 发送 cust 值。

关于如何验证这一点没有错误的任何帮助?

【问题讨论】:

UniqueTogetherValidation 类总是强加一个隐式约束,它所应用的所有字段总是按要求处理。具有默认值的字段是一个例外,因为即使在用户输入中省略时,它们也始终提供一个值。 (已复制)coderedirect.com/questions/625774/… 【参考方案1】:

customer 是一个只读字段。这意味着DRF 仅在创建对象后将其用于响应。但在UniqueTogetherValidator 中,它需要数据才能创建它。

正如DRF 在文档中所说:

UniqueTogetherValidator 类总是强加一个隐式约束,它所应用的所有字段总是按要求处理。具有默认值的字段是一个例外,因为即使在用户输入中省略时,它们也始终提供一个值。

所以需要手动处理:

class customerSerializer(serializers.ModelSerializer):
    publicAdd = AddressSerializer(many=True)

    class Meta:
        model = customerMaster
        fields = ['id','publicAdd']

    def create(self, validated_data):
        Address = validated_data.pop('publicAdd')
        customer = customerMaster.objects.create(**validated_data)
        for addres in Address:
           publicAddress.objects.create(customer=customer, **addres)
        return customer

    def validate(self, attrs):
        # customer is not in attrs because it's read-only
        # Maybe you need to add context data to your serializer or get it somehow you know
        object_exists = publicAddress.objects.filter(
            customer=your_customer, someValue=attrs["someValue"]
        ).exists()
        if object_exists:
            raise serializer.ValidationError("Duplicate object")
        return attrs

【讨论】:

是的,我知道,我正在检查 read_only_field 的更新方法,但它再次要求提供客户数据。我刚刚阅读了文档,发现验证器(这种方式)强制要求字段始终是必需的。现在我将不得不在视图或验证方法中编写自定义验证。 现在找到您的更新答案。

以上是关于嵌套可写序列化程序上的验证错误的主要内容,如果未能解决你的问题,请参考以下文章

Django 可写嵌套序列化程序更新

使用 Django Rest Framework 3.2.2 具有现有对象的可写嵌套序列化程序

如何在实例中有自定义 .update() 以更新 DRF 可写嵌套序列化程序中的多对多关系时更新值

`.create()` 方法默认不支持可写嵌套字段。

Django Rest Framework 中嵌套序列化程序的唯一验证

需要 Django Rest Framework 嵌套序列化程序 = False 错误