Interview frequency: …
Short answer
The WSGI or ASGI server receives the request, which passes through the middleware chain in the order set in MIDDLEWARE, then the URL resolver matches the path to a view, and the response returns through the middleware in reverse order.
Explanation
Each middleware is a function or class that wraps what follows it: code before get_response works on the request, and code after it works on the response. That is why order matters: SecurityMiddleware first, and SessionMiddleware before AuthenticationMiddleware because the latter reads the session. Django works with ASGI to support async views, but the ORM is still synchronous in many parts and is called through sync_to_async or its async interfaces such as aget and acount.
Code example
import time
import logging
logger = logging.getLogger(__name__)
class TimingMiddleware:
def __init__(self, get_response):
self.get_response = get_response # Once at startup
def __call__(self, request):
start = time.perf_counter()
response = self.get_response(request) # The rest of the chain and the view
response["Server-Timing"] = f"app;dur={(time.perf_counter() - start) * 1000:.1f}"
return response
# settings.py
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"app.middleware.TimingMiddleware",
]Common mistakes
- Placing a middleware that depends on request.user before AuthenticationMiddleware.
- Running synchronous ORM queries inside an async view without sync_to_async.
Follow-up questions
- What is the difference between WSGI and ASGI, and how does Flask manage the request context?
- What is the N+1 problem in the Django ORM and how do you solve it with select_related and prefetch_related?