
Django REST Framework: Advanced API Development Patterns
Django REST Framework provides a comprehensive toolkit for building robust, scalable APIs. This guide explores advanced patterns for professional API development using DRF’s powerful features.

Advanced Serializer Patterns

DRF serializers handle complex data validation and transformation requirements:
from rest_framework import serializers
from django.contrib.auth.models import User
from django.db import transaction
import re
class DynamicFieldsSerializer(serializers.ModelSerializer):
def __init__(self, *args, **kwargs):
fields = kwargs.pop('fields', None)
super().__init__(*args, **kwargs)
if fields is not None:
allowed = set(fields)
existing = set(self.fields)
for field_name in existing - allowed:
self.fields.pop(field_name)
class UserDetailSerializer(DynamicFieldsSerializer):
full_name = serializers.SerializerMethodField()
profile_completion = serializers.SerializerMethodField()
class Meta:
model = User
fields = ['id', 'username', 'email', 'first_name', 'last_name',
'full_name', 'profile_completion', 'date_joined']
read_only_fields = ['id', 'date_joined']
def get_full_name(self, obj):
return f"{obj.first_name} {obj.last_name}".strip()
def get_profile_completion(self, obj):
fields = ['first_name', 'last_name', 'email']
completed = sum(1 for field in fields if getattr(obj, field))
return round((completed / len(fields)) * 100, 2)
class UserCreateSerializer(serializers.ModelSerializer):
password_confirm = serializers.CharField(write_only=True)
class Meta:
model = User
fields = ['username', 'email', 'password', 'password_confirm',
'first_name', 'last_name']
extra_kwargs = {'password': {'write_only': True}}
def validate(self, attrs):
if attrs['password'] != attrs.pop('password_confirm'):
raise serializers.ValidationError("Passwords don't match")
return attrs
def validate_password(self, value):
if len(value) < 8:
raise serializers.ValidationError("Password too short")
if not re.search(r'[A-Z]', value):
raise serializers.ValidationError("Must contain uppercase")
return value
@transaction.atomic
def create(self, validated_data):
return User.objects.create_user(**validated_data)
Advanced ViewSet Implementation

ViewSets provide powerful API organization with custom actions and filtering:
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from django_filters import rest_framework as filters
from django.db.models import Q
class UserFilter(filters.FilterSet):
search = filters.CharFilter(method='filter_search')
created_after = filters.DateTimeFilter(field_name='date_joined', lookup_expr='gte')
class Meta:
model = User
fields = ['is_active', 'is_staff']
def filter_search(self, queryset, name, value):
return queryset.filter(
Q(username__icontains=value) |
Q(email__icontains=value) |
Q(first_name__icontains=value) |
Q(last_name__icontains=value)
)
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
filterset_class = UserFilter
permission_classes = [IsAuthenticated]
def get_serializer_class(self):
if self.action == 'create':
return UserCreateSerializer
return UserDetailSerializer
def get_queryset(self):
queryset = User.objects.all()
# Optimize queries based on action
if self.action == 'list':
queryset = queryset.select_related()
# Permission-based filtering
if not self.request.user.is_staff:
queryset = queryset.filter(is_active=True)
return queryset
@action(detail=True, methods=['post'])
def set_password(self, request, pk=None):
user = self.get_object()
if request.user != user and not request.user.is_staff:
return Response({'error': 'Permission denied'},
status=status.HTTP_403_FORBIDDEN)
serializer = PasswordChangeSerializer(data=request.data)
if serializer.is_valid():
user.set_password(serializer.validated_data['password'])
user.save()
return Response({'message': 'Password updated'})
return Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
@action(detail=False, methods=['get'])
def statistics(self, request):
return Response({
'total_users': User.objects.count(),
'active_users': User.objects.filter(is_active=True).count(),
'staff_users': User.objects.filter(is_staff=True).count()
})
Django REST Framework's comprehensive features enable developers to build enterprise-grade APIs that handle complex business requirements while maintaining clean, maintainable code.