summaryrefslogtreecommitdiff
path: root/docs/middleware.txt
blob: d920e883707d29716427bd6df147a29f3fb63867 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
==========
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.middleware.doc.XViewMiddleware",
    )

Django applies middleware in the order it's defined in ``MIDDLEWARE_CLASSES``.

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`: http://www.djangoproject.com/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``, URLs that lack a trailing
  slash will be redirected to the same URL with a trailing slash. 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.

* Handles flat pages. Every time Django encounters a 404 -- either within
  a view or as a result of no URLconfs matching -- it will check the
  database of flat pages based on the current URL.

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).

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 removes the content from any response to a HEAD request and sets the
``Date`` and ``Content-Length`` response-headers.

django.middleware.sessions.SessionMiddleware
--------------------------------------------

Enables session support. See the `session documentation`_.

.. _`session documentation`: http://www.djangoproject.com/documentation/sessions/

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 middleware or
the appropriate view; it'll return that ``HttpResponse``.

process_view
------------

Interface: ``process_view(self, request, view_func, param_dict)``

``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.) ``param_dict`` is a dictionary of keyword arguments
that will be passed to the view -- NOT including the first 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 middleware or
the appropriate view; it'll return that ``HttpResponse``.

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
      default Django middleware classes are in ``django/middleware/`` in the
      Django distribution.

    * 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.