Building REST APIs with Django

 

Building REST APIs with Django — Serializers, ViewSets, and JWT Authentication

Modern applications are API-driven.

Mobile apps, React frontends, third-party integrations — all communicate through APIs. If you're building backend systems with Django, the most powerful way to create APIs is using Django REST Framework (DRF).

In this article, we’ll cover:

  • What DRF is

  • Serializers

  • ViewSets

  • Routers

  • JWT Authentication

  • Production best practices

Why Use Django REST Framework?

Django REST Framework provides:

✔ Easy API creation
✔ Built-in authentication
✔ Powerful serialization
✔ Browsable API interface
✔ Pagination, filtering, throttling

It turns Django into a production-ready API engine.

Step 1: Install DRF

pip install djangorestframework

Add to INSTALLED_APPS:

'rest_framework',

What Is a Serializer?

A serializer converts:

  • Complex data types (Models, QuerySets) → JSON

  • JSON → Python objects

It works similarly to Django Forms but for APIs.

Example Model

from django.db import models

class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)

Creating a Serializer

from rest_framework import serializers
from .models import Post

class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = '__all__'

That’s it — DRF handles validation and transformation.

Step 2: Creating a ViewSet

ViewSets combine logic for:

  • List

  • Retrieve

  • Create

  • Update

  • Delete

All in one class.

from rest_framework.viewsets import ModelViewSet
from .models import Post
from .serializers import PostSerializer

class PostViewSet(ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer

Much cleaner than writing separate views.

Step 3: Using Routers

Routers automatically generate URL patterns.

from rest_framework.routers import DefaultRouter
from .views import PostViewSet

router = DefaultRouter()
router.register(r'posts', PostViewSet)

urlpatterns = router.urls

Now you automatically get:

  • GET /posts/

  • POST /posts/

  • GET /posts/{id}/

  • PUT /posts/{id}/

  • DELETE /posts/{id}/

JWT Authentication (Stateless & Scalable)

For modern applications, JWT (JSON Web Tokens) is commonly used.

Install:

pip install djangorestframework-simplejwt

Add to settings:

REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
}

Add JWT URLs

from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)

urlpatterns = [
path('api/token/', TokenObtainPairView.as_view()),
path('api/token/refresh/', TokenRefreshView.as_view()),
]

How JWT Works

  1. User logs in with username/password

  2. Server returns:

    • Access token

    • Refresh token

  3. Client sends access token in headers:

Authorization: Bearer <token>

No session storage required — fully stateless.

Protecting API Endpoints

from rest_framework.permissions import IsAuthenticated

class PostViewSet(ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
permission_classes = [IsAuthenticated]

Only authenticated users can access.

Advanced API Concepts

DRF also supports:

Filtering

from django_filters.rest_framework import DjangoFilterBackend

filter_backends = [DjangoFilterBackend]
filterset_fields = ['title']

Pagination

REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS':
'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10
}

Custom Permissions

from rest_framework.permissions import BasePermission

class IsAdminUserOnly(BasePermission):
def has_permission(self, request, view):
return request.user.is_staff

Performance Best Practices

When building production APIs:

Use select_related & prefetch_related

Avoid N+1 query problems.

Limit Serializer Fields

Avoid sending unnecessary data.

Add Indexes to Frequently Queried Fields

Use Throttling

REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': [
'rest_framework.throttling.UserRateThrottle'
],
'DEFAULT_THROTTLE_RATES': {
'user': '100/day'
}
}

Real-World Architecture Pattern

In scalable backend systems:

  • Models handle DB logic

  • Serializers handle validation

  • ViewSets handle HTTP behavior

  • JWT handles stateless auth

  • Frontend (React / Mobile) consumes API

This clean separation makes Django ideal for full-stack systems.Using Django REST Framework, you can build secure, scalable, and production-ready APIs with minimal boilerplate.

✔ Serializers handle validation
✔ ViewSets simplify CRUD
✔ Routers manage URLs
✔ JWT ensures stateless authentication

Comments

Popular posts from this blog

Database Integration in FastAPI (SQLAlchemy CRUD)

Middleware & CORS in FastAPI

Python Data Handling