Why DRF Sometimes Feels Like Too Much Weight
If you’ve been part of the Django ecosystem, you’re likely familiar with Django Rest Framework (DRF). It’s a standard, powerful, and extremely comprehensive library. However, DRF often comes with a price: bulkiness. Defining complex Serializers or nesting classes just to return a few data fields can sometimes make a project heavier than necessary.
In a real-world project requiring over 1,500 requests per second, I once hit a bottleneck where the validation logic was too heavy. That’s when I turned to Django Ninja. The experience felt like bringing the flexibility of FastAPI into the solid framework of Django.
The core difference lies in Django Ninja’s use of Type Hints and Pydantic, which is also the foundation for SQLModel. This approach significantly reduces boilerplate code. According to many benchmarks, Pydantic v2 parses data 5-10 times faster than traditional DRF Serializers.
What is Django Ninja and Why Should You Care?
Simply put, Django Ninja is a library for building APIs based on modern Python 3 features. It doesn’t try to replace Django entirely; instead, it focuses on optimizing the API communication layer.
Here are the reasons why I prioritize using it for new microservices:
- Superior Performance: Thanks to Pydantic, data validation and conversion happen almost instantaneously.
- Automatic Documentation: Just write your code, and you’ll immediately have Swagger UI and ReDoc available at the
/docspath. - Type Safety: VS Code or PyCharm will provide highly accurate code suggestions, helping you catch errors while you type.
- Async Support: You can use
async defto handle I/O-bound tasks without blocking the system.
Getting Started: Building a Post Management API
To demonstrate its conciseness, we’ll build a small Blog application. I’ll assume you have already initialized a basic Django project.
Step 1: Installing the Library
Installation takes only a few seconds with the pip command:
pip install django-ninja
Step 2: Data Models
In the models.py file, we define a simple table structure:
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)
is_published = models.BooleanField(default=False)
Step 3: Defining Schemas with Pydantic
Instead of verbose Serializers, we use Schemas to describe input and output data. Create a schemas.py file:
from ninja import Schema
from datetime import datetime
class PostIn(Schema):
title: str
content: str
is_published: bool = False
class PostOut(Schema):
id: int
title: str
content: str
created_at: datetime
Separating In and Out allows for tighter data control. You’ll never have to worry about accidentally exposing sensitive fields like passwords or internal IDs.
Step 4: Implementing Endpoints
In the api.py file, you’ll notice an interesting similarity to FastAPI:
from ninja import NinjaAPI
from typing import List
from .models import Post
from .schemas import PostIn, PostOut
api = NinjaAPI()
@api.get("/posts", response=List[PostOut])
def list_posts(request):
return Post.objects.all()
@api.post("/posts", response=PostOut)
def create_post(request, data: PostIn):
post = Post.objects.create(**data.dict())
return post
The code looks clean and easy to maintain, following principles of professional code organization. Everything is clearly typed.
Step 5: Configuring Routing
Finally, register the API in the project’s urls.py:
from django.urls import path
from .api import api
urlpatterns = [
path("api/", api.urls),
]
Real-World Lessons: Validation and Optimization
One thing I absolutely love about Django Ninja is how it handles errors. If a user sends an incorrect format, the system automatically returns a 422 error code with a detailed description of the error location. You don’t need to write any manual exception handling code for these cases.
Pro tip: When working with large databases, combine Django Ninja with Django ORM’s .values() or .only(). Django Ninja processes these dictionaries extremely fast, significantly reducing server memory load, much like high-performance JSON serialization.
Testing Results with Swagger
Run the server and visit http://127.0.0.1:8000/api/docs. You’ll see a professional interactive interface. Here, you can “Try it out” on the endpoints without needing to open Postman.
Conclusion
Django Ninja wasn’t created to kill DRF. However, it is an excellent choice for projects that prioritize speed and conciseness. If you’re tired of verbose Serializer code, give Django Ninja a try. Your productivity will definitely see a significant boost.

