简体   繁体   中英

How to validate unique constraint on django rest framework?

How can i validate an unique constraint with a key that is not on the request payload?

The key that i need to validate are user_id and sku but the request does not contain the user_id key.

Example of payload:

{'sku': '123', data: []}

The serializers:

class ProductConfiguration(serializers.Serializer):

    min_quantity = serializers.IntegerField(required=True)
    price = serializers.DecimalField(
        required=True,
        decimal_places=2,
        max_digits=10,
        coerce_to_string=False
    )


class ProductSerializer(serializers.ModelSerializer):

    sku = serializers.CharField(required=True)
    data = ProductConfiguration(many=True, required=True)

    class Meta:
        model = WholeSale

        # the "id" and "user_id" columns should not be included on the response
        exclude = ['id', 'user']

I need to validate that the user and sku key already exist.

By default if the two keys user_id and sku were on the payload drf could take care of Unique error, how can i validate this two keys if one of them are not on the payload?

you can get user data from request

request.user

Maybe pass it in to serializer from view

data = request.data
data['user_id'] = request.user.pk
serializer = ProductSerializer(data)

in serializer you could do

def validate(self, data):
    user = data.get('user_id')
    sku = data.get('sku')

    record = WholeSale.objects.filter(user=user, sku=sku).first()

    if not record:
        raise serializers.ValidationError("This combo doesn't exist")

    return super().validate(data)
class ProductSerializer(serializers.ModelSerializer):
    def validate(self, attrs):
        if not Sku.objects.get(sku=attrs['sku']).exists() or not User.objects.get(id=attrs['id']).exists():
            raise serializers.ValidationError("Something doesn't exist")
        
        return attrs

    sku = serializers.CharField(required=True)
    data = ProductConfiguration(many=True, required=True)

    class Meta:
        model = WholeSale
        exclude = ['id', 'user']

Assuming that you have this model structure ( i am only taking the sku and user field). To achieve what you trying to do, in class meta provide a unique together constraints,

class WholeSale(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    sku = models.CharField(max_lenght=100)

    class Meta:
        unique_together = ['user', 'sku']

OR ,

simply overwrite the validate_unique method to achieve validation on both user and sku fields together.

class WholeSale(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    sku = models.CharField(max_lenght=100)

    def validate_unique(self, *args, **kwargs):
        # super(WholeSale, self).validate_unique(*args, **kwargs) # python2
        super().validate_unique(*args, **kwargs) # python3
        if self.__class__.objects.filter(user=self.user, sku=self.sku).\
            exists():
            raise ValidationError(
                message='This (user, sku) already exists.',
            )

No need to validate explicitly from serializer

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM