/blog/intercepting-requests-a-guide-to-custom-django-middleware/ - zsh
user@portfolio ~ $

cat intercepting-requests-a-guide-to-custom-django-middleware.md

Intercepting Requests: A Guide to Custom Django Middleware

Author: Aslany Rahim Published: December 02, 2025
Middleware is the "Onion" of Django. Learn how to write custom hooks that process every request entering your application and every response leaving it.

Have you ever wondered how Django knows who a logged-in user is on every view? Or how CRSF protection works globally? The answer is Middleware.

Middleware is a framework of hooks into Django’s request/response processing. It's a light, low-level "plugin" system for globally altering Django’s input or output.

The Onion Architecture

Think of your Django app as the center of an onion.
1. When a Request comes in from the internet, it passes through the layers of the onion (Middleware) from the outside in.
2. It hits your View (the center).
3. The Response travels back out through the layers from the inside out.

Writing Custom Middleware

Let's solve a real-world problem. We want to measure exactly how long every request takes to process and add that time to a custom HTTP header.

Create a file middleware.py in your app folder.

import time

class TimingMiddleware:
    def __init__(self, get_response):
        # One-time configuration and initialization.
        self.get_response = get_response

    def __call__(self, request):
        # Code to be executed for each request BEFORE
        # the view (and later middleware) are called.
        start_time = time.time()

        # This line actually calls the view (or the next middleware)
        response = self.get_response(request)

        # Code to be executed for each request/response AFTER
        # the view is called.
        duration = time.time() - start_time

        # Add custom header
        response['X-Page-Generation-Duration-ms'] = int(duration * 1000)

        return response

Installing the Middleware

Django executes middleware in the order they are listed in settings.py.

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # ...
    'myapp.middleware.TimingMiddleware', # Add ours here
]

Another Example: IP Blocking

Imagine you are under attack from a specific IP address. You can block them before they even touch your database.

from django.core.exceptions import PermissionDenied

class IPBlockMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # In real life, load this from a database or cache (Redis)
        self.BANNED_IPS = ['123.45.67.89']

    def __call__(self, request):
        user_ip = request.META.get('REMOTE_ADDR')

        if user_ip in self.BANNED_IPS:
            raise PermissionDenied("You are banned.")

        return self.get_response(request)

Order Matters!

If you put your IPBlockMiddleware at the very bottom of the list, the request will go through Session middleware, Authentication middleware, and everything else before it gets blocked. That's a waste of resources.

Security middleware usually belongs at the top of the list.

Conclusion

Middleware is powerful because it allows you to apply logic globally without repeating code in every single View. Whether it's logging, authentication, styling headers, or exception handling, middleware is the place to do it.

41 views
0 comments

Comments (0)

Leave a Comment

No comments yet. Be the first to comment!

Related Posts

Real-Time Django: Building a Chat App with WebSockets

Standard HTTP is strictly Request-Response. To build a real-time chat or notification system, you need persistent connections. Learn how to …

December 08, 2025

Level Up Your Django Tests: Switching from Unittest to Pytest

Standard Django testing is verbose. Discover why the Python community is moving to Pytest, how to use Fixtures effectively, and …

December 06, 2025

REST vs. GraphQL: Is it Time to Switch in Django?

Tired of hitting three different API endpoints just to render one profile page? We compare the traditional REST approach with …

December 03, 2025

user@portfolio ~ $ _