Django documentation

Middleware

This document is for Django's SVN release, which can be significantly different from previous releases. Get old docs here: 0.96, 0.95.

Middleware is a framework of hooks into Django’s request/response processing. It’s a light, low-level “plugin” system for globally altering Django’s input and/or output.

Each middleware component is responsible for doing some specific function. For example, Django includes a middleware component, XViewMiddleware, that adds an "X-View" HTTP header to every response to a HEAD request.

This document explains all middleware components that come with Django, how to use them, and how to write your own middleware.

Activating middleware

To activate a middleware component, add it to the MIDDLEWARE_CLASSES list in your Django settings. In MIDDLEWARE_CLASSES, each middleware component is represented by a string: the full Python path to the middleware’s class name. For example, here’s the default MIDDLEWARE_CLASSES created by django-admin.py startproject:

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.middleware.doc.XViewMiddleware',
)

Django applies middleware in the order it’s defined in MIDDLEWARE_CLASSES, except in the case of response and exception middleware, which is applied in reverse order.

A Django installation doesn’t require any middleware — e.g., MIDDLEWARE_CLASSES can be empty, if you’d like — but it’s strongly suggested that you use CommonMiddleware.

Available middleware

django.middleware.cache.CacheMiddleware

Enables site-wide cache. If this is enabled, each Django-powered page will be cached for as long as the CACHE_MIDDLEWARE_SECONDS setting defines. See the cache documentation.

django.middleware.common.CommonMiddleware

Adds a few conveniences for perfectionists:

  • Forbids access to user agents in the DISALLOWED_USER_AGENTS setting, which should be a list of strings.

  • Performs URL rewriting based on the APPEND_SLASH and PREPEND_WWW settings.

    If APPEND_SLASH is True and the initial URL doesn’t end with a slash, and it is not found in the URLconf, then a new URL is formed by appending a slash at the end. If this new URL is found in the URLconf, then Django redirects the request to this new URL. Otherwise, the initial URL is processed as usual.

    For example, foo.com/bar will be redirected to foo.com/bar/ if you don’t have a valid URL pattern for foo.com/bar but do have a valid pattern for foo.com/bar/.

    New in Django development version: The behavior of APPEND_SLASH has changed slightly in the development version. It didn’t used to check whether the pattern was matched in the URLconf.

    If PREPEND_WWW is True, URLs that lack a leading “www.” will be redirected to the same URL with a leading “www.”

    Both of these options are meant to normalize URLs. The philosophy is that each URL should exist in one, and only one, place. Technically a URL foo.com/bar is distinct from foo.com/bar/ — a search-engine indexer would treat them as separate URLs — so it’s best practice to normalize URLs.

  • Handles ETags based on the USE_ETAGS setting. If USE_ETAGS is set to True, Django will calculate an ETag for each request by MD5-hashing the page content, and it’ll take care of sending Not Modified responses, if appropriate.

django.middleware.doc.XViewMiddleware

Sends custom X-View HTTP headers to HEAD requests that come from IP addresses defined in the INTERNAL_IPS setting. This is used by Django’s automatic documentation system.

django.middleware.gzip.GZipMiddleware

Compresses content for browsers that understand gzip compression (all modern browsers).

It is suggested to place this first in the middleware list, so that the compression of the response content is the last thing that happens. Will not compress content bodies less than 200 bytes long, when the response code is something other than 200, Javascript files (for IE compatibitility), or responses that have the Content-Encoding header already specified.

django.middleware.http.ConditionalGetMiddleware

Handles conditional GET operations. If the response has a ETag or Last-Modified header, and the request has If-None-Match or If-Modified-Since, the response is replaced by an HttpNotModified.

Also sets the Date and Content-Length response-headers.

django.middleware.http.SetRemoteAddrFromForwardedFor

Sets request.META['REMOTE_ADDR'] based on request.META['HTTP_X_FORWARDED_FOR'], if the latter is set. This is useful if you’re sitting behind a reverse proxy that causes each request’s REMOTE_ADDR to be set to 127.0.0.1.

Important note: This does NOT validate HTTP_X_FORWARDED_FOR. If you’re not behind a reverse proxy that sets HTTP_X_FORWARDED_FOR automatically, do not use this middleware. Anybody can spoof the value of HTTP_X_FORWARDED_FOR, and because this sets REMOTE_ADDR based on HTTP_X_FORWARDED_FOR, that means anybody can “fake” their IP address. Only use this when you can absolutely trust the value of HTTP_X_FORWARDED_FOR.

django.middleware.locale.LocaleMiddleware

Enables language selection based on data from the request. It customizes content for each user. See the internationalization documentation.

django.contrib.sessions.middleware.SessionMiddleware

Enables session support. See the session documentation.

django.contrib.auth.middleware.AuthenticationMiddleware

Adds the user attribute, representing the currently-logged-in user, to every incoming HttpRequest object. See Authentication in Web requests.

django.contrib.csrf.middleware.CsrfMiddleware

New in Django development version

Adds protection against Cross Site Request Forgeries by adding hidden form fields to POST forms and checking requests for the correct value. See the Cross Site Request Forgery protection documentation.

django.middleware.transaction.TransactionMiddleware

Binds commit and rollback to the request/response phase. If a view function runs successfully, a commit is done. If it fails with an exception, a rollback is done.

The order of this middleware in the stack is important: middleware modules running outside of it run with commit-on-save - the default Django behavior. Middleware modules running inside it (coming later in the stack) will be under the same transaction control as the view functions.

See the transaction management documentation.

Writing your own middleware

Writing your own middleware is easy. Each middleware component is a single Python class that defines one or more of the following methods:

process_request

Interface: process_request(self, request)

request is an HttpRequest object. This method is called on each request, before Django decides which view to execute.

process_request() should return either None or an HttpResponse object. If it returns None, Django will continue processing this request, executing any other middleware and, then, the appropriate view. If it returns an HttpResponse object, Django won’t bother calling ANY other request, view or exception middleware, or the appropriate view; it’ll return that HttpResponse. Response middleware is always called on every response.

process_view

Interface: process_view(self, request, view_func, view_args, view_kwargs)

request is an HttpRequest object. view_func is the Python function that Django is about to use. (It’s the actual function object, not the name of the function as a string.) view_args is a list of positional arguments that will be passed to the view, and view_kwargs is a dictionary of keyword arguments that will be passed to the view. Neither view_args nor view_kwargs include the first view argument (request).

process_view() is called just before Django calls the view. It should return either None or an HttpResponse object. If it returns None, Django will continue processing this request, executing any other process_view() middleware and, then, the appropriate view. If it returns an HttpResponse object, Django won’t bother calling ANY other request, view or exception middleware, or the appropriate view; it’ll return that HttpResponse. Response middleware is always called on every response.

process_response

Interface: process_response(self, request, response)

request is an HttpRequest object. response is the HttpResponse object returned by a Django view.

process_response() should return an HttpResponse object. It could alter the given response, or it could create and return a brand-new HttpResponse.

process_exception

Interface: process_exception(self, request, exception)

request is an HttpRequest object. exception is an Exception object raised by the view function.

Django calls process_exception() when a view raises an exception. process_exception() should return either None or an HttpResponse object. If it returns an HttpResponse object, the response will be returned to the browser. Otherwise, default exception handling kicks in.

Guidelines

  • Middleware classes don’t have to subclass anything.
  • The middleware class can live anywhere on your Python path. All Django cares about is that the MIDDLEWARE_CLASSES setting includes the path to it.
  • Feel free to look at Django’s available middleware for examples. The core Django middleware classes are in django/middleware/ in the Django distribution. The session middleware is in django/contrib/sessions.
  • If you write a middleware component that you think would be useful to other people, contribute to the community! Let us know, and we’ll consider adding it to Django.

Questions/Feedback

If you notice errors with this documentation, please open a ticket and let us know!

Please only use the ticket tracker for criticisms and improvements on the docs. For tech support, ask in the IRC channel or post to the django-users list.