Django Middleware
Processing requests and responses globally
🔄 What is Django Middleware?
Middleware is a framework of hooks that process requests and responses globally before they reach views or after they leave. It's like a security checkpoint that every request passes through.
# Simple middleware example
class SimpleMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# Code before view
response = self.get_response(request)
# Code after view
return response
Key Middleware Concepts
Security
Protect your application from attacks
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
]
Authentication
Handle user sessions and authentication
MIDDLEWARE = [
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
]
CORS
Enable cross-origin resource sharing
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
]
Logging
Track requests and responses
class LoggingMiddleware:
def __call__(self, request):
print(f"Request: {request.path}")
return self.get_response(request)
🔹 Creating Custom Middleware
Middleware processes every request and response in your Django application. It's useful for logging, authentication checks, or modifying requests globally. Here's how to create a simple custom middleware that adds a custom header to every response.
# middleware.py
class CustomHeaderMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# Process request before view
print(f"Processing: {request.path}")
# Get response from view
response = self.get_response(request)
# Modify response after view
response['X-Custom-Header'] = 'Hello from Middleware'
return response
Explanation:
__init__: Initializes middleware once when server starts
__call__: Runs for every request
get_response: Calls the next middleware or view
🔹 Registering Middleware
Add your middleware to settings.py in the MIDDLEWARE list. Order matters - middleware executes top to bottom for requests and bottom to top for responses.
# settings.py
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'myapp.middleware.CustomHeaderMiddleware', # Your custom middleware
]
🔹 Middleware with Process Methods
Advanced middleware can hook into different stages of request/response processing using special methods for more control over the request lifecycle.
class AdvancedMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
return self.get_response(request)
def process_view(self, request, view_func, view_args, view_kwargs):
# Called before view executes
print(f"View: {view_func.__name__}")
return None
def process_exception(self, request, exception):
# Called when view raises exception
print(f"Error: {exception}")
return None
def process_template_response(self, request, response):
# Called after view returns TemplateResponse
response.context_data['extra'] = 'Added by middleware'
return response
Hook Methods:
process_view: Runs before the view function
process_exception: Handles exceptions from views
process_template_response: Modifies template responses
🔹 Practical Example: Request Timer
This middleware measures how long each request takes to process, useful for performance monitoring and optimization.
import time
class RequestTimerMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# Start timer
start_time = time.time()
# Process request
response = self.get_response(request)
# Calculate duration
duration = time.time() - start_time
# Add to response header
response['X-Request-Duration'] = f"{duration:.3f}s"
print(f"{request.path} took {duration:.3f} seconds")
return response
Output Example:
/home/ took 0.045 seconds
/api/users/ took 0.123 seconds
/admin/ took 0.089 seconds