Django REST Framework Serializers – Full Guide
Tech3Space13 Apr 2026
Django REST Framework Serializers – Full Guide
We'll create serializers for all models with best practices:
- Proper nesting
- Read-only fields
- SlugField handling
- Count fields (likes, comments, members)
- Role-based information
- Validation where needed
1. Create the Serializers File
Create a file: serializers.py inside your app (e.g., community/serializers.py)
from rest_framework import serializers
from django.contrib.auth import get_user_model
from .models import (
Community, CommunityPost, CommunityNote, CommunityCollection,
CommunityMembership, PostLike, Comment, Tag
)
User = get_user_model()
2. Basic User Serializer (Reusable)
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'username', 'first_name', 'last_name', 'email']
read_only_fields = ['id']
3. Tag Serializer
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = ['id', 'name']
4. Community Serializers
# Simple Community Serializer (for listing)
class CommunityListSerializer(serializers.ModelSerializer):
member_count = serializers.IntegerField(source='members.count', read_only=True)
post_count = serializers.IntegerField(source='community_posts.count', read_only=True)
created_by = UserSerializer(read_only=True)
class Meta:
model = Community
fields = [
'id', 'name', 'slug', 'description', 'is_public',
'member_count', 'post_count', 'created_by', 'created_at'
]
read_only_fields = ['slug']
# Detailed Community Serializer
class CommunityDetailSerializer(serializers.ModelSerializer):
members = UserSerializer(many=True, read_only=True)
member_count = serializers.IntegerField(source='members.count', read_only=True)
created_by = UserSerializer(read_only=True)
class Meta:
model = Community
fields = [
'id', 'name', 'slug', 'description',
'meta_title', 'meta_description', 'meta_keywords',
'is_public', 'member_count', 'created_by', 'created_at', 'updated_at'
]
read_only_fields = ['slug', 'created_by']
5. CommunityPost Serializers
class CommunityPostListSerializer(serializers.ModelSerializer):
author = UserSerializer(read_only=True)
community = serializers.SlugRelatedField(slug_field='slug', read_only=True)
tags = TagSerializer(many=True, read_only=True)
like_count = serializers.IntegerField(source='likes.count', read_only=True)
comment_count = serializers.IntegerField(source='comments.count', read_only=True)
is_liked = serializers.SerializerMethodField()
class Meta:
model = CommunityPost
fields = [
'id', 'title', 'slug', 'content', 'community',
'author', 'tags', 'like_count', 'comment_count',
'is_liked', 'created_at'
]
read_only_fields = ['slug']
def get_is_liked(self, obj):
request = self.context.get('request')
if request and request.user.is_authenticated:
return obj.likes.filter(user=request.user).exists()
return False
class CommunityPostDetailSerializer(serializers.ModelSerializer):
author = UserSerializer(read_only=True)
community = serializers.SlugRelatedField(slug_field='slug', read_only=True)
tags = TagSerializer(many=True, read_only=True)
like_count = serializers.IntegerField(source='likes.count', read_only=True)
comment_count = serializers.IntegerField(source='comments.count', read_only=True)
is_liked = serializers.SerializerMethodField()
class Meta:
model = CommunityPost
fields = [
'id', 'title', 'slug', 'content', 'community',
'author', 'tags', 'like_count', 'comment_count',
'is_liked', 'created_at', 'updated_at',
'meta_title', 'meta_description'
]
read_only_fields = ['slug', 'author']
def get_is_liked(self, obj):
request = self.context.get('request')
if request and request.user.is_authenticated:
return obj.likes.filter(user=request.user).exists()
return False
# Serializer for creating a new post
class CommunityPostCreateSerializer(serializers.ModelSerializer):
tags = serializers.PrimaryKeyRelatedField(
queryset=Tag.objects.all(), many=True, required=False
)
class Meta:
model = CommunityPost
fields = ['title', 'content', 'tags', 'community']
def validate_community(self, value):
# Optional: Add permission check - user must be member of community
request = self.context.get('request')
if request and not value.members.filter(id=request.user.id).exists():
raise serializers.ValidationError("You must be a member of this community to post.")
return value
6. Comment Serializer (with Nested Replies)
class CommentSerializer(serializers.ModelSerializer):
user = UserSerializer(read_only=True)
replies = serializers.SerializerMethodField()
reply_count = serializers.IntegerField(source='replies.count', read_only=True)
class Meta:
model = Comment
fields = [
'id', 'user', 'content', 'parent',
'replies', 'reply_count', 'created_at'
]
read_only_fields = ['user']
def get_replies(self, obj):
if obj.replies.exists():
return CommentSerializer(obj.replies.all(), many=True).data
return []
# For creating comment
class CommentCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = ['content', 'parent', 'post']
7. CommunityNote Serializer
class CommunityNoteSerializer(serializers.ModelSerializer):
author = UserSerializer(read_only=True)
community = serializers.SlugRelatedField(slug_field='slug', read_only=True)
class Meta:
model = CommunityNote
fields = [
'id', 'title', 'content', 'file',
'author', 'community', 'created_at'
]
read_only_fields = ['author']
8. CommunityCollection Serializer
class CommunityCollectionSerializer(serializers.ModelSerializer):
community = serializers.SlugRelatedField(slug_field='slug', read_only=True)
posts = CommunityPostListSerializer(many=True, read_only=True)
notes = CommunityNoteSerializer(many=True, read_only=True)
post_count = serializers.IntegerField(source='posts.count', read_only=True)
note_count = serializers.IntegerField(source='notes.count', read_only=True)
class Meta:
model = CommunityCollection
fields = [
'id', 'name', 'description', 'community',
'posts', 'notes', 'post_count', 'note_count',
'created_at'
]
9. CommunityMembership Serializer
class CommunityMembershipSerializer(serializers.ModelSerializer):
user = UserSerializer(read_only=True)
community = serializers.SlugRelatedField(slug_field='slug', read_only=True)
role = serializers.CharField()
class Meta:
model = CommunityMembership
fields = ['id', 'user', 'community', 'role', 'joined_at']
read_only_fields = ['joined_at']
10. PostLike Serializer (Simple)
class PostLikeSerializer(serializers.ModelSerializer):
class Meta:
model = PostLike
fields = ['user', 'post']
read_only_fields = ['user']
Best Practices Used:
- Separate serializers for List vs Detail vs Create (performance optimized)
- Used
SerializerMethodFieldfor dynamic fields likeis_liked - Proper use of
read_only_fields - Context-aware methods (
requestin context) - SlugRelatedField for clean URLs
- Validation for business logic (e.g., must be member to post)
How to Use in Views (Quick Example)
# Example in views.py
class CommunityPostListCreateView(generics.ListCreateAPIView):
serializer_class = CommunityPostListSerializer
queryset = CommunityPost.objects.select_related('author', 'community')
def get_serializer_class(self):
if self.request.method == 'POST':
return CommunityPostCreateSerializer
return CommunityPostListSerializer
Would you like me to also provide:
- ViewSets and URLs for all models?
- Permissions (IsMember, IsAdmin, IsModerator)?
- Pagination and Filtering setup?
- Nested Serializer Improvements?
Just tell me what you need next! I'm happy to continue building this step by step.