How to perform data validation in Django Rest Framework?

How to perform data validation in Django Rest Framework?

Three ways to perform data validation in Django Rest Framework serializers

In Django Rest Framework (DRF), we get serializers to serialize our native Python data types into JSON or XML, serializers can also perform deserialization along with serialization. This means a serializer can convert a native Python data type such as List, Tuple, Querysets etc. into a representable JSON format, as well as it can take JSON and convert it back to the relevant python data type.

Django Rest Framework applies data validation at the time of deserialization, that is why we need to call is_valid() method before accessing the validated data from a serializer instance. If the data is invalid, in this case, errors are then appended to the serializer's error property and a ValidationError will be thrown.

We can apply data validation in various ways, in this blog, we will have a look at three ways we can apply data validation in a Django Rest Framework (DRF) serializer.

For this blog, we are going to use ModelSerializer and which will be based on the given model throughout this blog.

# app_name/models.py

from django.db import models

class Book(models.Model):
    name = models.CharField(max_length=100)
    rating = models.PositiveSmallIntegerField()
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    ...

Instance (object) validation:

If you have a Book model as given above, and you want to validate the whole instance, here is how you can perform instance validation.

In Django Rest Framework (DRF) serializers, we can use a validation() method to perform object or instance level validation, which will take object or instance as an argument and always return the instance of the Model if not then it will raise a ValidationError.

# app_name/serializers.py

from rest_framework import serializers
from app_name.models import Book

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'

    def validate(self, data):
        if data['author'] == self.context["request"].user:
            raise serializers.ValidationError('Logged in User is not an Author')
        return data

Field level validation:

If you have a Book model as given above, and you want to validate certain fields such as rating for that model, here is how you can perform field-level validation.

The thing to note here is that if you are performing the validation on a field, the validate_FIELD_NAME method will be used which will always return the validated value, if not then it will raise a ValidationError.

In the below example, we are validating whether the logged-in user is an author or not.

# app_name/serializers.py

from rest_framework import serializers
from app_name.models import Book

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'

    def validate_rating(self, value):
        if value < 1 or value > 10:
            raise serializers.ValidationError('Rating has to be between 1 and 10.')
        return value

Validation through validators:

In the above example of Field level validation, we have validated the field through a method validate_FIELD_NAME, but you can also create a custom validator to perform such an operation.

# app_name/serializers.py

from rest_framework import serializers
from app_name.models import Book

def is_rating_valid(value):
    if value < 1:
        raise serializers.ValidationError('Value cannot be lower than 1.')
    elif value > 10:
        raise serializers.ValidationError('Value cannot be higher than 10')

class BookSerializer(serializers.ModelSerializer):
    rating = serializers.IntegerField(validators=[is_rating_valid])
    class Meta:
        model = Book
        fields = '__all__'

That’s it for this blog, there can be some other ways as well if you want to perform some validation, but it is highly recommended that you should perform the data validation in the serializer if possible.

Any thoughts? Write it down in the comments.

For more such crispy blogs daily, follow Dev.Junction, subscribe to our newsletter and get notified.

Did you find this article valuable?

Support Dev.Junction by becoming a sponsor. Any amount is appreciated!