diff -r 5ff1fc726848 -r c6bca38c1cbf parts/django/docs/topics/http/middleware.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/parts/django/docs/topics/http/middleware.txt Sat Jan 08 11:20:57 2011 +0530 @@ -0,0 +1,179 @@ +========== +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 how middleware works, how you activate middleware, and +how to write your own middleware. Django ships with some built-in middleware +you can use right out of the box; they're documented in the :doc:`built-in +middleware reference `. + +Activating middleware +===================== + +To activate a middleware component, add it to the :setting:`MIDDLEWARE_CLASSES` +list in your Django settings. In :setting:`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 :setting:`MIDDLEWARE_CLASSES` +created by :djadmin:`django-admin.py startproject `:: + + MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + ) + +During the request phases (:meth:`process_request` and :meth:`process_view` +middleware), Django applies middleware in the order it's defined in +:setting:`MIDDLEWARE_CLASSES`, top-down. During the response phases +(:meth:`process_response` and :meth:`process_exception` middleware), the +classes are applied in reverse order, from the bottom up. You can think of it +like an onion: each middleware class is a "layer" that wraps the view: + +.. image:: _images/middleware.png + :width: 502 + :height: 417 + :alt: Middleware application order. + +A Django installation doesn't require any middleware -- e.g., +:setting:`MIDDLEWARE_CLASSES` can be empty, if you'd like -- but it's strongly +suggested that you at least use +:class:`~django.middleware.common.CommonMiddleware`. + +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: + +.. _request-middleware: + +``process_request`` +------------------- + +.. method:: process_request(self, request) + +``request`` is an :class:`~django.http.HttpRequest` object. This method is +called on each request, before Django decides which view to execute. + +``process_request()`` should return either ``None`` or an +:class:`~django.http.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 :class:`~django.http.HttpResponse` object, +Django won't bother calling ANY other request, view or exception middleware, or +the appropriate view; it'll return that :class:`~django.http.HttpResponse`. +Response middleware is always called on every response. + +.. _view-middleware: + +``process_view`` +---------------- + +.. method:: process_view(self, request, view_func, view_args, view_kwargs) + +``request`` is an :class:`~django.http.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 :class:`~django.http.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 :class:`~django.http.HttpResponse` object, Django won't bother +calling ANY other request, view or exception middleware, or the appropriate +view; it'll return that :class:`~django.http.HttpResponse`. Response +middleware is always called on every response. + +.. _response-middleware: + +``process_response`` +-------------------- + +.. method:: process_response(self, request, response) + +``request`` is an :class:`~django.http.HttpRequest` object. ``response`` is the +:class:`~django.http.HttpResponse` object returned by a Django view. + +``process_response()`` must return an :class:`~django.http.HttpResponse` +object. It could alter the given ``response``, or it could create and return a +brand-new :class:`~django.http.HttpResponse`. + +Unlike the ``process_request()`` and ``process_view()`` methods, the +``process_response()`` method is always called, even if the ``process_request()`` +and ``process_view()`` methods of the same middleware class were skipped because +an earlier middleware method returned an :class:`~django.http.HttpResponse` +(this means that your ``process_response()`` method cannot rely on setup done in +``process_request()``, for example). In addition, during the response phase the +classes are applied in reverse order, from the bottom up. This means classes +defined at the end of :setting:`MIDDLEWARE_CLASSES` will be run first. + +.. _exception-middleware: + +``process_exception`` +--------------------- + +.. method:: process_exception(self, request, exception) + +``request`` is an :class:`~django.http.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 +:class:`~django.http.HttpResponse` object. If it returns an +:class:`~django.http.HttpResponse` object, the response will be returned to +the browser. Otherwise, default exception handling kicks in. + +Again, middleware are run in reverse order during the response phase, which +includes ``process_exception``. If an exception middleware return a response, +the middleware classes above that middleware will not be called at all. + +``__init__`` +------------ + +Most middleware classes won't need an initializer since middleware classes are +essentially placeholders for the ``process_*`` methods. If you do need some +global state you may use ``__init__`` to set up. However, keep in mind a couple +of caveats: + + * Django initializes your middleware without any arguments, so you can't + define ``__init__`` as requiring any arguments. + + * Unlike the ``process_*`` methods which get called once per request, + ``__init__`` gets called only *once*, when the Web server starts up. + +Marking middleware as unused +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It's sometimes useful to determine at run-time whether a piece of middleware +should be used. In these cases, your middleware's ``__init__`` method may raise +``django.core.exceptions.MiddlewareNotUsed``. Django will then remove that +piece of middleware from the middleware process. + +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 :setting:`MIDDLEWARE_CLASSES` setting includes + the path to it. + + * Feel free to look at :doc:`Django's available middleware + ` for examples. + + * If you write a middleware component that you think would be useful to + other people, contribute to the community! :doc:`Let us know + `, and we'll consider adding it to Django.