Serializers0%
Serializers
Beginner12 min read•Updated: Jul 11, 2026
Serializers
In API development, data must be converted from complex Python objects (such as Django model instances and QuerySets) into machine-readable formats like JSON, and vice versa. Django REST Framework (DRF) Serializers handle both serialization (Python objects -> JSON) and deserialization (JSON -> validated Python data) with powerful validation pipelines.
1. Serialization vs Deserialization
Output
Serialization (Read / GET):
Model Instance (Article) ──► Serializer ──► Python dict ──► JSON string (Client)
Deserialization (Write / POST):
Client JSON payload ──► Serializer.is_valid() ──► Validated data ──► Model Instance saved
2. Implementing an Enterprise ModelSerializer
ModelSerializer inspects model fields and generates serializer fields, validators, and default create() / update() methods automatically:
Python
# articles/serializers.py
from rest_framework import serializers
from .models import Article, Category, Tag
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = ["id", "title"]
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ["id", "name", "slug"]
class ArticleSerializer(serializers.ModelSerializer):
# 1. Read-only nested representation
category = CategorySerializer(read_only=True)
# 2. Write-only field for passing category ID during mutations
category_id = serializers.PrimaryKeyRelatedField(
queryset=Category.objects.all(),
source="category",
write_only=True
)
# 3. Read-only field displaying author username
author_username = serializers.CharField(source="author.username", read_only=True)
# 4. Computed custom field via SerializerMethodField
reading_time_minutes = serializers.SerializerMethodField()
class Meta:
model = Article
fields = [
"id",
"title",
"slug",
"content",
"status",
"author_username",
"category",
"category_id",
"reading_time_minutes",
"created_at",
]
read_only_fields = ["id", "slug", "created_at"]
def get_reading_time_minutes(self, obj: Article) -> int:
# Calculate reading time assuming 200 words per minute
word_count = len(obj.content.split())
return max(1, round(word_count / 200))
# Field-level validator
def validate_title(self, value):
if len(value) < 5:
raise serializers.ValidationError("Title must be at least 5 characters.")
return value
3. Customizing create() and update()
When nested or relational fields require explicit processing:
Python
class ArticleCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ["title", "content", "category", "tags"]
def create(self, validated_data):
# Extract M2M tags if present
tags_data = validated_data.pop("tags", [])
# Create parent instance
article = Article.objects.create(**validated_data)
# Attach tags
article.tags.set(tags_data)
return article
4. Serializer Validation Workflow
Python
# Inspecting and validating incoming request data
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid():
# Access validated data dictionary
clean_data = serializer.validated_data
# Save instance (calls create() or update())
instance = serializer.save(author=request.user)
else:
# Access validation error dictionary
print(serializer.errors)
Interactive Quiz
Practice Quiz
Question 1
What two primary functions do Django REST Framework serializers perform?
Question 2
What does a SerializerMethodField accomplish?
Question 3
How do you mark a serializer field so that it appears in GET responses but is rejected if clients send it in POST/PUT requests?
Question 4
What attribute holds cleaned, validated data after calling serializer.is_valid()?
Question 5
Why is ModelSerializer preferred over the base Serializer class when working with Django models?
Next Lesson
APIView & ViewSet
Continue learning with hands-on practice, examples, and exercises in the upcoming topic.
Related Lessons
| Previous Lesson | Next Lesson |
|---|---|
| URL Dispatcher and Routing | APIView & ViewSet |
Practice Quiz
Test your understanding of this lesson with 5 questions. Each question has one correct answer.