Django REST Framework (DRF)

Master Django REST Framework including serializers, ViewSets, authentication, permissions, throttling, pagination, and API best practices.

📝 Serializers

  • 23. What are Django REST Framework (DRF) Serializers?
    Convert model instances into JSON/XML and handle validation/deserialization. They bridge the gap between Django models and API responses.
    from rest_framework import serializers
    from .models import User
    
    class UserSerializer(serializers.ModelSerializer):
        class Meta:
            model = User
            fields = '__all__'  # or ['id', 'name', 'email']
            # read_only_fields = ['id', 'created_at']
  • 24. Difference Between Serializer and ModelSerializer
    Serializer: Define fields manually with full control
    ModelSerializer: Auto-generates fields from a Django model
    # Regular Serializer
    class UserSerializer(serializers.Serializer):
        id = serializers.IntegerField(read_only=True)
        name = serializers.CharField(max_length=100)
        email = serializers.EmailField()
        
        def create(self, validated_data):
            return User.objects.create(**validated_data)
    
    # ModelSerializer (shorter)
    class UserSerializer(serializers.ModelSerializer):
        class Meta:
            model = User
            fields = ['id', 'name', 'email']

🎯 Views & ViewSets

  • 25. What are APIView, ViewSet, and Router in DRF?
    APIView: Base class for manually handling HTTP methods (get, post, etc.)
    ViewSet: Simplifies CRUD operations using predefined methods (list, retrieve, create, update, destroy)
    Router: Automatically maps URLs to ViewSet actions
    # APIView
    from rest_framework.views import APIView
    from rest_framework.response import Response
    
    class UserList(APIView):
        def get(self, request):
            users = User.objects.all()
            serializer = UserSerializer(users, many=True)
            return Response(serializer.data)
        
        def post(self, request):
            serializer = UserSerializer(data=request.data)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=201)
            return Response(serializer.errors, status=400)
    # ViewSet
    from rest_framework import viewsets
    
    class UserViewSet(viewsets.ModelViewSet):
        queryset = User.objects.all()
        serializer_class = UserSerializer
    
    # Router
    from rest_framework.routers import DefaultRouter
    
    router = DefaultRouter()
    router.register(r'users', UserViewSet)
    urlpatterns = router.urls

🔐 Authentication

  • 26. What Authentication Methods Does DRF Support?
    BasicAuthenticationSessionAuthenticationTokenAuthenticationRemoteUserAuthenticationJWT (via package)OAuth2 (via package)
    # settings.py
    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': [
            'rest_framework.authentication.TokenAuthentication',
            'rest_framework.authentication.SessionAuthentication',
        ]
    }
    
    # Token Authentication Setup
    # 1. Add 'rest_framework.authtoken' to INSTALLED_APPS
    # 2. Run migrations
    python manage.py migrate
    
    # 3. Create token for user
    from rest_framework.authtoken.models import Token
    token = Token.objects.create(user=user)
    
    # 4. Use in API calls
    # Header: Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b

🔒 Permissions

  • 27. How Do You Implement Permissions in DRF?
    Permissions control API access at view or object level.
    Built-in:AllowAnyIsAuthenticatedIsAdminUserIsAuthenticatedOrReadOnly
    # Global settings
    REST_FRAMEWORK = {
        'DEFAULT_PERMISSION_CLASSES': [
            'rest_framework.permissions.IsAuthenticated',
        ]
    }
    
    # Per view
    from rest_framework.permissions import IsAuthenticated
    
    class UserViewSet(viewsets.ModelViewSet):
        queryset = User.objects.all()
        serializer_class = UserSerializer
        permission_classes = [IsAuthenticated]
    # Custom Permission
    from rest_framework import permissions
    
    class IsOwner(permissions.BasePermission):
        def has_object_permission(self, request, view, obj):
            return obj.user == request.user
    
    class PostViewSet(viewsets.ModelViewSet):
        queryset = Post.objects.all()
        serializer_class = PostSerializer
        permission_classes = [IsAuthenticated, IsOwner]

⚡ Throttling

  • 28. What is Throttling in DRF?
    Prevents abuse by limiting request rates per user/IP.
    Types: UserRateThrottle, AnonRateThrottle, ScopedRateThrottle
    # settings.py
    REST_FRAMEWORK = {
        'DEFAULT_THROTTLE_CLASSES': [
            'rest_framework.throttling.AnonRateThrottle',
            'rest_framework.throttling.UserRateThrottle'
        ],
        'DEFAULT_THROTTLE_RATES': {
            'anon': '100/day',
            'user': '1000/day'
        }
    }
    
    # Per view
    from rest_framework.throttling import UserRateThrottle
    
    class OncePerDayUserThrottle(UserRateThrottle):
        rate = '1/day'
    
    class ContactViewSet(viewsets.ModelViewSet):
        throttle_classes = [OncePerDayUserThrottle]

📄 Pagination

  • 29. How Do You Implement Pagination in DRF?
    Use built-in paginators to break large result sets into pages.
    # settings.py
    REST_FRAMEWORK = {
        'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
        'PAGE_SIZE': 10
    }
    
    # Custom Pagination
    from rest_framework.pagination import PageNumberPagination
    
    class CustomPagination(PageNumberPagination):
        page_size = 20
        page_size_query_param = 'page_size'
        max_page_size = 100
    
    class UserViewSet(viewsets.ModelViewSet):
        queryset = User.objects.all()
        serializer_class = UserSerializer
        pagination_class = CustomPagination
    Other pagination styles:
    • LimitOffsetPagination
    • CursorPagination (for very large datasets)

📁 File Uploads

  • 30. How Do You Handle File Uploads in DRF?
    Use FileField or ImageField in serializers.
    # Serializer
    class UploadSerializer(serializers.Serializer):
        file = serializers.FileField()
        description = serializers.CharField()
    
    # View
    from rest_framework.parsers import MultiPartParser, FormParser
    
    class FileUploadView(APIView):
        parser_classes = [MultiPartParser, FormParser]
        
        def post(self, request):
            serializer = UploadSerializer(data=request.data)
            if serializer.is_valid():
                file = serializer.validated_data['file']
                # Handle file
                return Response({'message': 'File uploaded'})
            return Response(serializer.errors, status=400)
    For large files: Use chunked upload, streaming, or S3 direct upload

💾 Caching in DRF

  • 38. How to Implement Caching in DRF APIs?
    from django.views.decorators.cache import cache_page
    from django.utils.decorators import method_decorator
    
    # For class-based views
    @method_decorator(cache_page(60 * 15), name='dispatch')
    class UserViewSet(viewsets.ReadOnlyModelViewSet):
        queryset = User.objects.all()
        serializer_class = UserSerializer
    
    # For function-based views
    from rest_framework.decorators import api_view
    
    @api_view(['GET'])
    @cache_page(60 * 15)
    def user_list(request):
        users = User.objects.all()
        serializer = UserSerializer(users, many=True)
        return Response(serializer.data)

🎯 Best Practices

  • DRF API Best Practices
    • Use ViewSets for standard CRUD operations
    • Use APIView for custom logic
    • Always validate input data with serializers
    • Implement proper authentication and permissions
    • Use throttling to prevent API abuse
    • Implement pagination for large datasets
    • Use select_related() and prefetch_related()
    • Return appropriate HTTP status codes
    • Version your APIs (/api/v1/)
    • Document APIs with drf-spectacular or drf-yasg
    • Use filtering, searching, and ordering
    • Implement proper error handling
    • Use CORS headers correctly