serializers in Django Rest Framework


serializers in Django Rest Framework

Serializers in django rest framework are similar to django forms. By using django rest framework serializers we can serialize and deserialize the data. We can also validate the incoming data using django rest framework serializers to maintain the integrity of the data. We can divide the django rest framework serializers into two categories.

  1. Normal Serializers
    • It simply validates the data and performs the serialization and deserialization. For normal serializers we need implement the serializer methods like "save" and "update".
    • We also need to specify the each and every field of serializer externally and also in the serializer meta class "fields" attribute.
  2. Model serializers
    • It comes with advanced features like in-built functionality for "save", "update".
    • Unlike the normal serializers we can simply provide "fields" in the serializer meta class and no need to write external fields.

In this article we will only practice about the normal serializers.

Creating a django rest framework serializer class

In django rest framework we use "Serializer" as a base class for all the serializers. we import it from "rest_framework.serializers" module. Let's create a student serializer class.

from rest_framework import serializers

class StudentSerializer(serializers.Serializer):
    first_name = serializers.CharField(max_length=100)
    last_name = serializers.CharField(max_length=100)
    dob = serializers.DateField(required=False)
    college = serializers.CharField(max_length=100)
    address = serializers.CharField(max_length=100)

we have created a serializer class for a "Student" that takes student information like "first_name", "last_name", "dob" (date of birth) and address. In above serializers we have used serializer fields "CharField", "DateField" only. We can find many more fields at "http://www.django-rest-framework.org/api-guide/fields/". Every django rest framework serializer takes 2 parameters "instance", "data" as initializers.

Working with django rest framework serializers

serializer = StudentSerializer(instance=None, data={})
# let's validate the serializer
serializer.is_valid()
# Output: False
# get errors
print(serializer.errors)
#{'address': [ErrorDetail(string='This field is required.', code='required')],
# 'college': [ErrorDetail(string='This field is required.', code='required')],
# 'first_name': [ErrorDetail(string='This field is required.', code='required')],
# 'last_name': [ErrorDetail(string='This field is required.', code='required')]}

In above code we have created the serializer instance with no instance and no data. After, we have validated the serializer against the data. By default every field in the serializer has a validator(i.e field required) . To avoid the field required validator we can specify "required=False"  in the serializer field. We can validate the serializer by calling the method "is_valid()". It will return the boolean(True/False) value. If the serializer is not valid then we can get errors by using the attribute "errors". Note: "errors" attribute only available after calling the method "is_valid()"  otherwise serializer will raise the errors.

data = {'first_name': 'John', 'last_name': 'Williams',
'college': 'University of Columbia', 'address': '1-4h, Columbia'}
serializer = StudentSerializer(data=data)
# check if serializer is valid
serializer.is_valid()
# output: True
# access the validated data
serializer.validated_data
# OrderedDict([
# ('first_name', 'John'),
# ('last_name', 'Williams'),
# ('college', 'University of Columbia'),
# ('address', '1-4h, Columbia')])

In the above code we provided the serializer with valid data. We validated the serializer with the method "is_valid()" and it returned "True". It means the provided data is valid. Now, access the validated data from the serializer using the attribute "validated_data". Note: "errors" attribute only available after calling the method "is_valid()"  otherwise serializer will raise the errors.

Custom validations in django rest serializers

we have two types of serializer validators 1.field validation using "validate_<field_name>" method, 2.common validation using "validate" method

field validation using "validate_<field_name>" method

from datetime import date
from rest_framework import serializers

class StudentSerializer(serializers.Serializer):
    first_name = serializers.CharField(max_length=80)
    dob = serializers.DateField()

    def validate_dob(self, dob):
        if dob > date.today():
            raise serializers.ValidationError("Future date not allowed")
        return dob
# let's test it
serializer = StudentSerializer(data={'first_name': 'Anji', 'dob': '2100-12-12'})
serializer.is_valid()
# ouput: False
serializer.errors
# output: {'dob': [ErrorDetail(string='Future date not allowed', code='invalid')]}

In above code we have written custom validator for field "dob". The validation method recieves the argument as the value of the field afterconverting it into a python object.

common validation using "validate" method

from rest_framework import serializers

class EventSerializer(serializers.Serializer):
    description = serializers.CharField(max_length=100)
    start = serializers.DateTimeField()
    finish = serializers.DateTimeField()

    def validate(self, data):
        """
        Check that the start is before the stop.
        """
        if data['start'] > data['finish']:
            raise serializers.ValidationError("finish must occur after start")
        return data
# let's test it
serializer = EventSerializer(data={
    'description': 'desc',
    'start': '2100-12-12 0:0:0',
    'finish': '2050-12-03 0:0:0'
})
print(serializer.is_valid())
# output: False
print(serializer.errors)
# {'non_field_errors':[ErrorDetail(string='finish must occur after start',code='invalid')]}

In the above code we have writer a common validation method for all the fields instead individual fields. The method receives the data() after converting fields data into equivalent python objects.  In the next article we will discuss about django rest framework model serializers

Reference: http://www.django-rest-framework.org/tutorial/1-serialization/