Understanding Django Middleware: A Practical Guide

Search for a command to run...

No comments yet. Be the first to comment.
I recently tackled an interesting challenge that I think could benefit others in the community. The problem? Creating a symmetrical ManyToMany filter widget in the Django admin dashboard. You know, the kind where you can filter and select related obj...
Large Language Models (LLMs) have taken the world by storm, powering everything from smart search engines to intelligent business automation. But as their use grows, so does the need to monitor, evaluate, and debug these complex AI systems in real ti...

Have you ever had your code become too tightly coupled, making it hard to test and maintain? Some people certainly have. Let me share a story about how dependency injection would help you write better, more maintainable Go code. The Problem: A Coffee...
Domain-Driven Design (DDD) is an approach to software development that focuses on understanding and modeling the business domain. In this post, we'll explore how to implement DDD principles using Go, with practical examples and clear explanations. Wh...
I recently tackled an interesting challenge that I think could benefit others in the community. The problem? Creating a symmetrical ManyToMany filter widget in the Django admin dashboard. You know, the kind where you can filter and select related obj...

Django middleware is a powerful tool that allows you to process requests and responses globally across your entire Django application. In this post, we'll explore what middleware is, how it works, and walk through some practical examples.
Middleware in Django is a framework of hooks into Django's request/response processing. It's a lightweight, low-level plugin system for globally altering Django's input or output.
Each middleware component is responsible for doing some specific function. For example, Django includes a middleware that adds the CSRF token to responses and another that handles user sessions.
Middleware classes are called in the order they're defined in the MIDDLEWARE setting. During the request phase, Django calls the process_request() method of each middleware in order. During the response phase, the process_response() methods are called in reverse order.
Here's a simplified view of the request/response cycle:
Request comes in
Middleware 1 processes request
Middleware 2 processes request
View processes request and produces response
Middleware 2 processes response
Middleware 1 processes response
Response goes out
Let's look at some examples of custom middleware:
This middleware will measure how long each request takes to process:
import time
class TimingMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
start_time = time.time()
response = self.get_response(request)
duration = time.time() - start_time
response['X-Page-Generation-Duration-ms'] = int(duration * 1000)
return response
This middleware adds an X-Page-Generation-Duration-ms header to each response, showing how many milliseconds the request took to process.
This middleware will restrict access to certain views based on IP address:
from django.http import HttpResponseForbidden
class IPRestrictionMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
allowed_ips = ['192.168.1.1', '192.168.1.2']
ip = request.META.get('REMOTE_ADDR')
if request.path.startswith('/admin/') and ip not in allowed_ips:
return HttpResponseForbidden("You are not allowed to access this resource.")
return self.get_response(request)
This middleware checks if the request is for the admin area and if so, verifies that the client's IP is in the allowed list.
This middleware will log details about each request:
import logging
logger = logging.getLogger(__name__)
class RequestLoggingMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
logger.info(f"Request: {request.method} {request.path} from {request.META.get('REMOTE_ADDR')}")
response = self.get_response(request)
logger.info(f"Response: {response.status_code}")
return response
This middleware logs the HTTP method, path, and IP address for each request, as well as the status code of each response.
To use your custom middleware, add it to the MIDDLEWARE setting in your Django settings file:
MIDDLEWARE = [
# ... other middleware classes ...
'path.to.TimingMiddleware',
'path.to.IPRestrictionMiddleware',
'path.to.RequestLoggingMiddleware',
]
Remember, the order matters! Middleware classes are processed in the order they appear in this list.
Middleware is a powerful feature in Django that allows you to process requests and responses globally. Whether you're adding security features, logging information, or modifying responses, middleware provides a clean and reusable way to add functionality to your Django application.
By creating custom middleware, you can keep your views clean and focused on their primary logic, while handling cross-cutting concerns at the application level.