Writing Custom Middleware
Custom middleware lets you add global functionality — logging, timing, IP blocking, maintenance mode, custom headers. A middleware class implements __call__ and optionally process_view, process_exception, and process_template_response.
20 min•By Priygop Team•Updated 2026
Custom Middleware Structure
- Class with __init__(self, get_response)
- __call__(self, request) — Main logic
- Call get_response(request) to pass to next middleware
- Code BEFORE get_response = request processing
- Code AFTER get_response = response processing
- process_exception(request, exception) — Handle view exceptions
- Register in settings.MIDDLEWARE list
Custom Middleware Examples
Custom Middleware Examples
# mysite/middleware.py
# Request timing middleware
# import time
# import logging
# logger = logging.getLogger(__name__)
# class RequestTimingMiddleware:
# def __init__(self, get_response):
# self.get_response = get_response
#
# def __call__(self, request):
# start = time.time()
# response = self.get_response(request)
# duration = time.time() - start
# logger.info(f"{request.method} {request.path} - {duration:.2f}s")
# response['X-Request-Duration'] = f"{duration:.4f}"
# return response
# Maintenance mode middleware
# class MaintenanceMiddleware:
# def __init__(self, get_response):
# self.get_response = get_response
#
# def __call__(self, request):
# if settings.MAINTENANCE_MODE and not request.user.is_staff:
# return HttpResponse('Site under maintenance', status=503)
# return self.get_response(request)
# settings.py
# MIDDLEWARE = [
# ...
# 'mysite.middleware.RequestTimingMiddleware',
# 'mysite.middleware.MaintenanceMiddleware',
# ]Tip
Tip
Use __init__ for one-time setup and __call__ for per-request logic. process_view, process_exception are optional hooks.
Diagram
Loading diagram…
QuerySets are LAZY — no DB hit until evaluated.
Common Mistake
Warning
Doing heavy processing in middleware. It runs on EVERY request. Use caching or move heavy logic to views/celery tasks.
Practice Task
Note
(1) Create middleware that blocks certain IP addresses. (2) Add exception handling middleware. (3) Test with different requests.
Quick Quiz
Key Takeaways
- Custom middleware lets you add global functionality — logging, timing, IP blocking, maintenance mode, custom headers.
- Class with __init__(self, get_response)
- __call__(self, request) — Main logic
- Call get_response(request) to pass to next middleware