SyntaxStudy
Sign Up
Django Django REST Framework: Serializers
Django Beginner 1 min read

Django REST Framework: Serializers

Django REST Framework (DRF) is the de facto standard library for building REST APIs with Django. Serializers are at the heart of DRF — they convert complex data types like model instances and QuerySets into Python native datatypes that can be rendered into JSON or XML. They also handle deserialization: validating and converting incoming JSON data into Python objects. ModelSerializer is the most common serializer class. Similar to ModelForm, it introspects a model and automatically generates fields and validators. The Meta class specifies the model and which fields to include. You can add extra validation by writing validate_() methods or a validate() method for cross-field validation, just like with forms. Nested serializers allow you to represent related objects inline in the JSON output. SerializerMethodField lets you add computed or custom fields that don't exist on the model. It calls a get_() method on the serializer to produce the field value. This is useful for adding URLs (using request.build_absolute_uri()), computed counts, or data from related models without fetching extra database rows for each object.
Example
# blog/serializers.py — DRF serializers
from rest_framework import serializers
from django.contrib.auth import get_user_model
from .models import Post, Tag, Category

User = get_user_model()


class TagSerializer(serializers.ModelSerializer):
    class Meta:
        model  = Tag
        fields = ['id', 'name', 'slug']


class AuthorSerializer(serializers.ModelSerializer):
    class Meta:
        model  = User
        fields = ['id', 'username', 'email']


class PostSerializer(serializers.ModelSerializer):
    author   = AuthorSerializer(read_only=True)
    tags     = TagSerializer(many=True, read_only=True)
    tag_ids  = serializers.PrimaryKeyRelatedField(
        queryset=Tag.objects.all(), many=True, write_only=True, source='tags',
    )
    url          = serializers.SerializerMethodField()
    reading_time = serializers.SerializerMethodField()

    class Meta:
        model  = Post
        fields = [
            'id', 'title', 'slug', 'author', 'category',
            'body', 'tags', 'tag_ids', 'status',
            'published_at', 'url', 'reading_time',
        ]
        read_only_fields = ['slug', 'published_at']

    def get_url(self, obj):
        request = self.context.get('request')
        return request.build_absolute_uri(f'/api/posts/{obj.pk}/')

    def get_reading_time(self, obj):
        return max(1, round(len(obj.body.split()) / 200))

    def validate_title(self, value):
        if len(value) < 5:
            raise serializers.ValidationError('Title must be at least 5 characters.')
        return value