========== Middleware ========== 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`_. .. _`cache documentation`: ../cache/#the-per-site-cache 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`_. .. _`internationalization documentation`: ../i18n/ django.contrib.sessions.middleware.SessionMiddleware ---------------------------------------------------- Enables session support. See the `session documentation`_. .. _`session documentation`: ../sessions/ 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`_. .. _Authentication in Web requests: ../authentication/#authentication-in-web-requests 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`_. .. _`transaction management documentation`: ../transactions/ 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.