You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
169 lines
6.9 KiB
169 lines
6.9 KiB
.. _topics-http-middleware: |
|
|
|
========== |
|
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 :ref:`built-in |
|
middleware guide <ref-middleware>`. |
|
|
|
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 <startproject>`:: |
|
|
|
MIDDLEWARE_CLASSES = ( |
|
'django.middleware.common.CommonMiddleware', |
|
'django.contrib.sessions.middleware.SessionMiddleware', |
|
'django.contrib.auth.middleware.AuthenticationMiddleware', |
|
'django.middleware.doc.XViewMiddleware', |
|
) |
|
|
|
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()`` should 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`. |
|
|
|
.. _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. |
|
|
|
``__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 :mod:`Django's available middleware for examples |
|
<django.middleware>`. 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! :ref:`Let us know |
|
<internals-contributing>`, and we'll consider adding it to Django.
|
|
|