Open-Source Wikis

/

Django

/

Systems

/

Middleware

django/django

Middleware

django/middleware/ ships the built-in middleware classes. Per-app middleware lives alongside the contrib apps that own it (django/contrib/auth/middleware.py, django/contrib/sessions/middleware.py, etc.). The middleware mechanism itself — middleware compilation and dispatch — lives in django/core/handlers/base.py.

Purpose

Provide composable hooks that wrap every request and response. Middleware can short-circuit a request (return early), enrich the request (add request.user, request.session), transform a response (gzip, set CSP headers), or react to exceptions.

Middleware architecture

Since 1.10, middleware is "factory style":

def middleware(get_response):
    # one-time setup
    def _inner(request):
        # before
        response = get_response(request)
        # after
        return response
    return _inner

Or as a class:

class MyMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        ...

    def process_exception(self, request, exception):
        ...

    def process_template_response(self, request, response):
        ...

get_response is the next middleware down the chain (or the URL resolver + view at the bottom). The compilation in BaseHandler.load_middleware() walks MIDDLEWARE in reverse, threading each instance with the next-up callable.

The legacy four-method protocol (process_request, process_view, process_response, process_exception) is still supported via django.utils.deprecation.MiddlewareMixin for backwards compatibility.

Async-capable middleware

A middleware class can declare itself sync-, async-, or both-capable:

class MyMiddleware:
    sync_capable = True
    async_capable = True

When the middleware chain is being built for an ASGI handler, BaseHandler checks each middleware's capability and bridges via asgiref.sync.sync_to_async / async_to_sync where necessary. A pure-async chain runs without bridging; a pure-sync chain runs without bridging; a mixed chain has bridges inserted at the boundaries.

The sync_and_async_middleware decorator on a class indicates dual capability.

Built-in middleware

django/middleware/
├── cache.py             # CacheMiddleware, UpdateCacheMiddleware, FetchFromCacheMiddleware
├── clickjacking.py      # XFrameOptionsMiddleware
├── common.py            # CommonMiddleware (APPEND_SLASH, PREPEND_WWW, ETag, Content-Length)
├── csp.py               # ContentSecurityPolicyMiddleware
├── csrf.py              # CsrfViewMiddleware (~19 KB)
├── gzip.py              # GZipMiddleware
├── http.py              # ConditionalGetMiddleware (If-Modified-Since, If-None-Match)
├── locale.py            # LocaleMiddleware (sets request.LANGUAGE_CODE, prefixes URLs)
└── security.py          # SecurityMiddleware (HSTS, content-type sniff, referrer policy, …)

Plus, in contrib apps:

  • django/contrib/auth/middleware.pyAuthenticationMiddleware, LoginRequiredMiddleware, PersistentRemoteUserMiddleware.
  • django/contrib/sessions/middleware.pySessionMiddleware.
  • django/contrib/messages/middleware.pyMessageMiddleware.
  • django/contrib/sites/middleware.pyCurrentSiteMiddleware.
  • django/contrib/redirects/middleware.pyRedirectFallbackMiddleware.
  • django/contrib/flatpages/middleware.pyFlatpageFallbackMiddleware.

Default ordering

The recommended default order from the docs (and the startproject template):

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",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
]

Order matters: SessionMiddleware must come before AuthenticationMiddleware (auth needs session). CsrfViewMiddleware must come before any view that uses CSRF tokens. LocaleMiddleware should come after SessionMiddleware so the locale can be read from the session.

Notable middleware

CsrfViewMiddleware

django/middleware/csrf.py is the largest middleware (~19 KB). It:

  • Sets a CSRF cookie on safe responses.
  • Validates the CSRF token on unsafe methods (POST, PUT, PATCH, DELETE).
  • Handles the Origin/Referer checks.
  • Supports the @csrf_exempt and @csrf_protect decorators.

CSRF tokens are masked at the wire level to prevent BREACH-style attacks; the unmask happens in middleware.

SecurityMiddleware

Sets a bundle of HTTP security headers from settings:

  • Strict-Transport-Security (SECURE_HSTS_SECONDS, SECURE_HSTS_INCLUDE_SUBDOMAINS, SECURE_HSTS_PRELOAD).
  • X-Content-Type-Options: nosniff (SECURE_CONTENT_TYPE_NOSNIFF).
  • Referrer-Policy (SECURE_REFERRER_POLICY).
  • Cross-Origin-Opener-Policy (SECURE_CROSS_ORIGIN_OPENER_POLICY).
  • HTTPS redirect (SECURE_SSL_REDIRECT, SECURE_SSL_HOST).

CommonMiddleware

Catches a few cross-cutting concerns:

  • APPEND_SLASH: redirects /foo to /foo/ if /foo doesn't exist but /foo/ does.
  • PREPEND_WWW: redirects bare host to www. host.
  • ETag generation: hashes responses for If-None-Match checks.
  • DISALLOWED_USER_AGENTS: rejects requests from blocklisted UAs.

CacheMiddleware

UpdateCacheMiddleware and FetchFromCacheMiddleware together implement full-page caching keyed on URL + Vary headers. They're typically wrapped in the per-view @cache_page decorator rather than installed globally.

LocaleMiddleware

Sets request.LANGUAGE_CODE and applies translations to the response. Also supports the i18n_patterns URL prefix mechanism — a request to /fr/articles/ is internally routed to /articles/ with French language activated.

GZipMiddleware

Compresses responses with gzip when the client supports it. Skips already-compressed responses. Implements the BREACH mitigation: never gzip responses that contain CSRF tokens, by default.

XFrameOptionsMiddleware

Sets the X-Frame-Options header (DENY, SAMEORIGIN, or unset). Per-view overrides via @xframe_options_exempt and friends.

ContentSecurityPolicyMiddleware

Added in 6.0. Sets Content-Security-Policy and Content-Security-Policy-Report-Only headers from SECURE_CSP and SECURE_CSP_REPORT_ONLY settings. The CSP utility class lives at django/utils/csp.py.

Integration points

  • Handlers (http) — compile and call middleware.
  • URL routing (urls) — process_view runs after URL resolution, before the view.
  • Sessions, auth, messages (contrib/) — each ships its own middleware.
  • Caching (core utilities) — cache_page decorator wraps cache middleware.
  • i18nLocaleMiddleware ties translation into the request cycle.

Entry points for modification

  • Custom middleware: define a callable factory or class with __init__(get_response) and __call__(request). Optionally implement process_view, process_exception, process_template_response.
  • Async support: declare sync_capable / async_capable and provide an async def __call__ if async_capable.
  • Settings-driven: read from django.conf.settings rather than constructor args.

Key source files

File Purpose
django/core/handlers/base.py Middleware compilation, get_response dispatch
django/middleware/csrf.py CSRF protection (~19 KB)
django/middleware/common.py APPEND_SLASH, ETag, content-length
django/middleware/security.py Security headers, HSTS, HTTPS redirect
django/middleware/cache.py Full-page caching
django/middleware/locale.py i18n integration
django/middleware/gzip.py gzip compression
django/middleware/clickjacking.py X-Frame-Options
django/middleware/csp.py CSP headers
django/middleware/http.py Conditional GET
django/utils/deprecation.py MiddlewareMixin (legacy)
django/utils/csp.py CSP value builder

Where to read tests

  • tests/middleware/ — built-in middleware behaviour.
  • tests/csrf_tests/CsrfViewMiddleware exhaustive coverage.
  • tests/middleware_exceptions/process_exception paths.
  • tests/cache/CacheMiddleware, cache_page.
  • tests/csp_tests/ — CSP middleware.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Middleware – Django wiki | Factory