Ranu Vijay
Ranu Vijay

Reputation: 1249

Validation error on nested writable serializer

I have a writable nested serializer like this -

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

this all works fine until I apply validation such as

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

And defining

read_only_fields = ('customer',)

in AddressSerializer won't help either.

Now it throws an error such as cust field is always required and to send the cust value via api.

Any help on how to validate this without an error?

Upvotes: 0

Views: 564

Answers (1)

Mojtaba Arezoomand
Mojtaba Arezoomand

Reputation: 2380

customer is a read-only field. it means DRF only uses it for responses after creating your object. but in UniqueTogetherValidator it needs data before creating it.

As DRF says in documentation:

The UniqueTogetherValidator class always imposes an implicit constraint that all the fields it applies to are always treated as required. Fields with default values are an exception to this as they always supply a value even when omitted from user input.

So you need to handle it manually:

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

Upvotes: 2

Related Questions