FastAPI vs Django

Rajesh PetheRajesh Pethe
4 min read

FastAPI vs Django: Key Differences

FastAPI and Django are both powerful web frameworks in Python, but they are designed for different use cases.

FastAPI is a sleek, high-performance framework for building APIs with Python. It is considered ideal for creating microservices.

Django on the other hand is a monolithic framework because it is designed to handle all aspects of a web application including back-end, front-end within one application. It can also be used to develop microservices using Django REST Framework.

Let's break down their differences and key features.

1. How is FastAPI Different from Django?

FastAPI and Django are both web frameworks, but they have different architectures and use cases.

Feature                                  FastAPI                                                      Django
PerformanceVery fast (async support, Starlette-based)Slower due to synchronous nature
Request HandlingAsynchronous (non-blocking)Synchronous (blocking by default)
Built-in FeaturesMinimal (needs external libraries)Comes with ORM, admin panel, authentication
Data ValidationPydantic (automatic type validation)Forms & serializers (manual validation)
Best ForHigh-performance APIs, real-time appsFull-stack web applications

2. Key Differences

  1. Async Support: FastAPI natively supports async/await for handling concurrent requests, while Django requires third-party libraries (e.g., Django Channels).
  2. Performance: FastAPI is faster due to its async nature and Starlette-based design.
  3. Built-in Features: Django provides an admin panel, authentication, and ORM, whereas FastAPI requires external libraries for most functionalities.

Dependency Injection in FastAPI vs Django

1. Dependency Injection in FastAPI

FastAPI provides a powerful dependency injection (DI) system, allowing easy injection of shared components like database connections.

Example: FastAPI Dependency Injection

from fastapi import FastAPI, Depends

app = FastAPI()

def get_db():
    return {"users": ["Alice", "Bob"]}  # Simulating a database

@app.get("/users/")
def get_users(db: dict = Depends(get_db)):
    return db["users"]

Here, get_db() is injected automatically into get_users().

2. Django Equivalent (Mocking Dependencies)

Django does not have built-in DI. Instead, dependencies are passed manually or mocked using patch.object().

from unittest.mock import patch
from django.test import TestCase

class UserTestCase(TestCase):
    @patch("app.views.get_db")
    def test_get_users(self, mock_db):
        mock_db.return_value = {"users": ["MockUser"]}
        response = self.client.get("/users/")
        self.assertEqual(response.json(), {"users": ["MockUser"]})

Mocking Dependencies in FastAPI Tests

1. Mocking Sync Dependencies

from fastapi.testclient import TestClient

def test_read_users():
    def mock_get_db():
        return {"users": ["MockUser1"]}

    app.dependency_overrides[get_db] = mock_get_db
    client = TestClient(app)
    response = client.get("/users/")
    assert response.json() == ["MockUser1"]
    app.dependency_overrides.clear()

2. Mocking Async Dependencies

FastAPI’s TestClient does not support async functions, so use httpx.AsyncClient.

import pytest
from httpx import AsyncClient

@pytest.mark.asyncio
async def test_get_users():
    async def mock_get_db():
        return {"users": ["MockUser1"]}

    app.dependency_overrides[get_db] = mock_get_db
    async with AsyncClient(app=app, base_url="http://test") as client:
        response = await client.get("/users/")

    assert response.json() == ["MockUser1"]
    app.dependency_overrides.clear()

Handling Long Async DB Queries in FastAPI

1. Immediate vs. Final Response

What happens when a request triggers a long async operation:

  1. Immediate Response: The API sends a 202 Accepted or task ID. Client can do other stuff and poll for previous task status.
  2. Final Response: The client must query the status via another endpoint.

2. Using Background Tasks

from fastapi import BackgroundTasks

async def long_db_query():
    await asyncio.sleep(10)
    print("DB query completed!")

@app.get("/start-task/")
async def start_task(background_tasks: BackgroundTasks):
    background_tasks.add_task(long_db_query)
    return {"message": "Task started", "status": "processing"}

3. Using Celery for Task Tracking

from celery import Celery
celery_app = Celery("tasks", broker="redis://localhost:6379/0")

@celery_app.task
def long_db_query():
    time.sleep(10)
    return "Query Complete!"

Client can check task status with:

@app.get("/task-status/{task_id}")
async def get_task_status(task_id: str):
    return {"task_id": task_id, "status": AsyncResult(task_id).status}

Real-Time Updates Using WebSockets

1. WebSocket Endpoint for Live Progress

from fastapi import WebSocket

@app.websocket("/progress")
async def progress_websocket(websocket: WebSocket):
    await websocket.accept()
    for i in range(1, 11):
        await asyncio.sleep(1)
        await websocket.send_text(f"Progress: {i * 10}%")
    await websocket.send_text("Task Completed!")
    await websocket.close()

2. Client-Side Code

let socket = new WebSocket("ws://127.0.0.1:8000/progress");

socket.onmessage = function(event) {
    console.log("Update from server:", event.data);
};

3. When to Use WebSockets

✅ Real-time progress tracking (e.g., file uploads)

✅ Live notifications (e.g., chat, stock prices)

✅ Streaming data updates


Conclusion

  • FastAPI supports async operations natively, unlike Django.
  • Dependency injection is simpler in FastAPI.
  • Testing async functions requires AsyncClient.
  • BackgroundTasks or Celery handle long tasks.
  • WebSockets enable real-time updates efficiently.
0
Subscribe to my newsletter

Read articles from Rajesh Pethe directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Rajesh Pethe
Rajesh Pethe

Passionate software engineer with 17+ years of experience in design and development of full life cycle commercial applications. Functional experience include Financial, Telecom and E-Commerce applications. Primary technical stack includes but not limited to Python, Django, REST, SQL, Perl, Unix/Linux. Secondary technical skills include Java, Angular and React JS. DevOps skills include CiCD, AWS, Docker, Kubernetes and Terraform.