Agustin Luques

Django Rest Framework - what are the Serializers?

logo

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.


instagram icon twitter icon linkedin icon github icon


Buy me a beer🍻

or

Invitame un café ☕️