Introduction to serializers in Django Rest Framework (DRF) Part 1

Published: (February 3, 2026 at 02:48 AM EST)
5 min read
Source: Dev.to

Source: Dev.to

What is a Serializer?

In DRF, a serializer is like a bridge between your database and the internet.

  • Django models store data as Python objects.
  • When you want to send that data to a frontend application (like React or a mobile app), you cannot send Python objects. You need to send a format that everyone understands – usually JSON.

Serializers perform three main jobs:

  1. Serialization: Converting complex Python objects (Models) into Python dictionaries (which can be easily rendered into JSON).
  2. Deserialization: Converting JSON data coming from a user back into complex Python objects.
  3. Validation: Checking if the incoming data is correct before saving it to the database.

Serialization and Deserialization

Why Do We Need Them?

In a standard Django application, we interact with data using Models. Let’s look at a simple scenario. We want to build a store, so we define a ProductModel.

(Create this in your models.py file)

from django.db import models

class ProductModel(models.Model):
    name = models.CharField(max_length=150)
    description = models.TextField()
    price = models.DecimalField(max_digits=10, decimal_places=2)
    stock = models.IntegerField()
    is_active = models.BooleanField(default=True)

    def __str__(self):
        return self.name

If you try to send a ProductModel instance directly to a web browser, it will crash. The browser doesn’t speak “Python Class”; it speaks “JSON”.

We need a translator. That translator is the Serializer.

Creating Your First Serializer

There are several types of serializers in DRF, such as ModelSerializer, HyperlinkedModelSerializer, and ListSerializer. To truly understand how they work, we will start with the base Serializer class.

Create a serializers.py file in your app (let’s call the app demo) and define a serializer that mirrors our model:

# demo/serializers.py
from rest_framework import serializers 

class ProductSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=150)
    description = serializers.CharField()
    price = serializers.DecimalField(max_digits=10, decimal_places=2)
    stock = serializers.IntegerField()
    is_active = serializers.BooleanField()

Note: We had to repeat the fields from the model. We will solve this redundancy in Part 2, but for now, this explicit style helps us understand exactly what is happening.

Seeing Serialization in Action

The best way to learn DRF is not through the web browser, but through the Python Shell. This allows us to see the data transformation step‑by‑step.

  1. Open your terminal and run the shell (make sure your virtual environment with Django and DRF is active):

    python manage.py shell
  2. Import the model and serializer:

    from demo.models import ProductModel
    from demo.serializers import ProductSerializer

Step 1: Create Dummy Data

Create a product in the database using standard Django code:

product = ProductModel.objects.create(
    name='Logitech MX Master',
    description='Ergonomic Logitech Mouse',
    price=110.99,
    stock=72,
    is_active=True
)

Step 2: Serialize the Data

Pass the product object into our serializer:

serializer = ProductSerializer(product)

To see the translated data, access the .data attribute:

print(serializer.data)

Output:

{
   "name": "Logitech MX Master",
   "description": "Ergonomic Logitech Mouse",
   "price": "110.99",
   "stock": 72,
   "is_active": true
}

Success! The serializer took a Python object and converted it into a Python dictionary. This dictionary can now be easily turned into JSON and sent over the API.

Deserialization (The Reverse Process)

Now, let’s look at the reverse scenario. A user wants to create a new product via your API. They will send you a JSON object.

Assume this is the incoming data:

data = {
    "name": "Mechanical Keyboard",
    "description": "Backlit mechanical keyboard",
    "price": "24.99",
    "stock": 10,
    "is_active": True
}

Pass the raw data to the serializer using the data argument:

serializer = ProductSerializer(data=data)

Common mistake: Trying to access .data before validation.

# DO NOT DO THIS
print(serializer.data)

You will get an error:

AssertionError: When a serializer is passed a `data` keyword argument you must call `.is_valid()` before accessing `.data`.

Proper Deserialization Flow

if serializer.is_valid():
    product_instance = serializer.save()   # creates a ProductModel instance
    print("Created:", product_instance)
else:
    print("Validation errors:", serializer.errors)
  • serializer.is_valid() runs the validation logic.
  • If the data passes validation, serializer.save() creates (or updates) the model instance.
  • If validation fails, serializer.errors contains a dictionary of error messages.

Recap

  • Serializers translate between Django models (Python objects) and JSON‑compatible data.
  • They handle serialization, deserialization, and validation.
  • Starting with the base Serializer class gives you a clear view of each step; later you’ll see how ModelSerializer removes the redundancy.

Accessing the Serialized .data Representation

# Example usage in the Django shell
serializer = ProductSerializer(data=product_data)
if serializer.is_valid():
    print(serializer.validated_data)
else:
    print(serializer.errors)

DRF protects your database. It refuses to let you touch the data until you confirm it is valid. You must call is_valid() first. If the is_valid() method is not called, Python will raise an AssertionError.

Since our data matches the requirements (e.g., price is a decimal, stock is an integer, is_active is a boolean), is_valid() returns True.

Saving the Data

Now that the data is valid, we want to save it to the database. Usually, you would call serializer.save().

However, if you try to run serializer.save() right now, it will fail.

Why? Because the base Serializer class doesn’t know how to create a ProductModel. We have to tell it how.

Implement the create() Method

Edit serializers.py and add a create() method:

class ProductSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=150)
    description = serializers.CharField()
    price = serializers.DecimalField(max_digits=10, decimal_places=2)
    stock = serializers.IntegerField()
    is_active = serializers.BooleanField()

    # We must implement this to support saving data
    def create(self, validated_data):
        # Unpack the validated data and create a model instance
        return ProductModel.objects.create(**validated_data)

Now, back in your shell, run:

serializer.save()

It will successfully create the “Mechanical Keyboard” in your database.

Wrap Up

We have successfully built a serializer that can:

  • Read a Django model and convert it to a dictionary.
  • Write: Take a dictionary, validate it, and convert it into a Django model.

But did you notice something annoying?
We repeated a lot of code. We typed name, price, and stock in the model, and then we typed them again in the serializer. In a real project with dozens of models, this violates the DRY (Don’t Repeat Yourself) principle.

In Part 2, we’ll introduce the ModelSerializer, a powerful shortcut that writes all this boilerplate code for you automatically.

References

Back to Blog

Related posts

Read more »

Searcher of lyrics's musics

Overview This application allows users to search for song lyrics by providing the band/artist name and the song title. The graphical interface is built with St...

Learning Python: The trenches

TL;DR I didn't expect Python to be as much of a pain and joy as it was. My Learning Journey I've been learning Python for the past three months and have had a...