Django Ninja: High-Speed REST API Development Made Easy

Python tutorial - IT technology blog
Python tutorial - IT technology blog

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 /docs path.
  • 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 def to 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.

Share: