Django Rest Framework - what are the Serializers?
I've been working with Django since the beginning of the year. My teammates and I decided to use Django Rest Framework because we had to make an API to be consumed by an Android client.
DRF is a very complete and well-documented framework. It is quite simple to use if you came from Django. There are the Serializers, though, a new concept that may not be user friendly.
Formal definition:
Serializers allow complex data such as querysets and model instances to be converted to native Python datatypes that can then be easily rendered into JSON, XML or other content types. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.
With simple words:
They are kind of intemediary from the JSONs, or other content types, in the views (user input) and the Django models
Hands-on
Serializing
Let's create a simple Django model first:
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
After running the migrations, we are ready to instantiate our Person.
from <app>.models import Person
me = Person(first_name='Agustin', last_name='Luques')
So, now we have already created our object. If you inspect this me
object, you will see that it's not a JSON. It is a complex type, though. What does it mean? It means that if we try to return this object by an HTTP call, you will run into an error.
import json
json.dumps(me)
# TypeError: Object of type Person is not JSON serializable
That's why we need a serializer. Let's define one.
from rest_framework import serializers
class PersonSerializer(serializers.Serializer):
first_name = serializers.CharField(max_length=30)
last_name = serializers.CharField(max_length=30)
We can now serialize our me
object!
serializer = PersonSerializer(me)
serializer.data
# {'first_name': 'Agustin', 'last_name': 'Luques'}
serializer.data
, as you can see, it's a plain python object which we can include into an HTTP Response.
json.dumps(serializer.data)
# '{"first_name": "Agustin", "last_name": "Luques"}'
Deserializing
I really think that here comes the beautiful use of the DRF serializers.
We are receiving a JSON object from the view. We have to save it in database. We can, manually, create the object as we did above. Fortunately, DRF provides us the serializers which will do all the job and will also run all the validations that the JSON needs to pass through.
Let's mock our JSON and see the magic!
jsonData = {'first_name': 'Agustin', 'last_name': 'Luques'}
Now, give it to our PersonSerializer
serializer = PersonSerializer(data=jsonData)
serializer.is_valid()
# True
serializer.validated_data
# OrderedDict([('first_name', 'Agustin'), ('last_name', 'Luques')])
Creation
We have the serializer.validated_data
. We need the Django model, though. For that, we use our serializer's method save()
but we have to implement a create()
method first.
class PersonSerializer(serializers.Serializer):
first_name = serializers.CharField(max_length=30)
last_name = serializers.CharField(max_length=30)
def create(self, validated_data):
return Person.objects.create(**validated_data)
We are ready to create to our Django model!
jsonData = {'first_name': 'Agustin', 'last_name': 'Luques'}
serializer = PersonSerializer(data=jsonData)
serializer.is_valid()
serializer.save()
# <Person: Person object (1)>
Validations
As you can see, we specified that both first_name
and last_name
can't be larger that 30 characters. So let's try breaking our serializer.
jsonData = {'first_name': 'This is a very large name with more than 30 characters', 'last_name': 'Luques'}
serializer = PersonSerializer(data=jsonData)
serializer.is_valid()
# False
serializer.errors
# {'first_name': [ErrorDetail(string='Ensure this field has no more than 30 characters.', code='max_length')]}
Conclusion
I explained the main concept of DRF Serializers but there are a lot of cool things you can do with them. Such as, custom validations, updates, add extra fields, read_only and write_only fields, etc.
The documentation is quite complete but you can reach me at any of my social medias.
or