Skip to content

Commit be9f291

Browse files
committed
Edited the middleware doc for completeness, clarity, and consistency.
1 parent ae8e973 commit be9f291

File tree

2 files changed

+113
-69
lines changed

2 files changed

+113
-69
lines changed

django/core/handlers/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def get_response(self, request):
134134
raise ValueError("The view %s.%s didn't return an HttpResponse object." % (callback.__module__, view_name))
135135

136136
# If the response supports deferred rendering, apply template
137-
# response middleware and the render the response
137+
# response middleware and then render the response
138138
if hasattr(response, 'render') and callable(response.render):
139139
for middleware_method in self._template_response_middleware:
140140
response = middleware_method(request, response)

docs/topics/http/middleware.txt

Lines changed: 112 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,28 @@ Middleware
44

55
Middleware is a framework of hooks into Django's request/response processing.
66
It's a light, low-level "plugin" system for globally altering Django's input
7-
and/or output.
7+
or output.
88

99
Each middleware component is responsible for doing some specific function. For
10-
example, Django includes a middleware component, ``XViewMiddleware``, that adds
11-
an ``"X-View"`` HTTP header to every response to a ``HEAD`` request.
10+
example, Django includes a middleware component,
11+
:class:`~django.middleware.transaction.TransactionMiddleware`, that wraps the
12+
processing of each HTTP request in a database transaction.
1213

1314
This document explains how middleware works, how you activate middleware, and
1415
how to write your own middleware. Django ships with some built-in middleware
15-
you can use right out of the box; they're documented in the :doc:`built-in
16+
you can use right out of the box. They're documented in the :doc:`built-in
1617
middleware reference </ref/middleware>`.
1718

1819
Activating middleware
1920
=====================
2021

21-
To activate a middleware component, add it to the :setting:`MIDDLEWARE_CLASSES`
22-
list in your Django settings. In :setting:`MIDDLEWARE_CLASSES`, each middleware
23-
component is represented by a string: the full Python path to the middleware's
24-
class name. For example, here's the default :setting:`MIDDLEWARE_CLASSES`
25-
created by :djadmin:`django-admin.py startproject <startproject>`::
22+
To activate a middleware component, add it to the
23+
:setting:`MIDDLEWARE_CLASSES` tuple in your Django settings.
24+
25+
In :setting:`MIDDLEWARE_CLASSES`, each middleware component is represented by
26+
a string: the full Python path to the middleware's class name. For example,
27+
here's the default value created by :djadmin:`django-admin.py startproject
28+
<startproject>`::
2629

2730
MIDDLEWARE_CLASSES = (
2831
'django.middleware.common.CommonMiddleware',
@@ -32,12 +35,33 @@ created by :djadmin:`django-admin.py startproject <startproject>`::
3235
'django.contrib.messages.middleware.MessageMiddleware',
3336
)
3437

35-
During the request phases (:meth:`process_request` and :meth:`process_view`),
36-
Django applies middleware in the order it's defined in
37-
:setting:`MIDDLEWARE_CLASSES`, top-down. During the response phases
38-
(:meth:`process_template_response`, :meth:`process_response`, and
39-
:meth:`process_exception`), the classes are applied in reverse order, from the
40-
bottom up.
38+
A Django installation doesn't require any middleware —
39+
:setting:`MIDDLEWARE_CLASSES` can be empty, if you'd like — but it's strongly
40+
suggested that you at least use
41+
:class:`~django.middleware.common.CommonMiddleware`.
42+
43+
The order in :setting:`MIDDLEWARE_CLASSES` matters because a middleware can
44+
depend on other middleware. For instance,
45+
:class:`~django.contrib.auth.middleware.AuthenticationMiddleware` stores the
46+
authenticated user in the session; therefore, it must run after
47+
:class:`~django.contrib.sessions.middleware.SessionMiddleware`.
48+
49+
Hooks and application order
50+
===========================
51+
52+
During the request phase, before calling the view, Django applies middleware
53+
in the order it's defined in :setting:`MIDDLEWARE_CLASSES`, top-down. Two
54+
hooks are available:
55+
56+
* :meth:`process_request`
57+
* :meth:`process_view`
58+
59+
During the response phase, after calling the view, middleware are applied in
60+
reverse order, from the bottom up. Three hooks are available:
61+
62+
* :meth:`process_exception` (only if the view raised an exception)
63+
* :meth:`process_template_response` (only for template responses)
64+
* :meth:`process_response`
4165

4266
.. image:: _images/middleware.svg
4367
:alt: middleware application order
@@ -47,10 +71,7 @@ bottom up.
4771
If you prefer, you can also think of it like an onion: each middleware class
4872
is a "layer" that wraps the view.
4973

50-
A Django installation doesn't require any middleware -- e.g.,
51-
:setting:`MIDDLEWARE_CLASSES` can be empty, if you'd like -- but it's strongly
52-
suggested that you at least use
53-
:class:`~django.middleware.common.CommonMiddleware`.
74+
The behavior of each hook is described below.
5475

5576
Writing your own middleware
5677
===========================
@@ -65,16 +86,19 @@ Python class that defines one or more of the following methods:
6586

6687
.. method:: process_request(self, request)
6788

68-
``request`` is an :class:`~django.http.HttpRequest` object. This method is
69-
called on each request, before Django decides which view to execute.
89+
``request`` is an :class:`~django.http.HttpRequest` object.
90+
91+
``process_request()`` is called on each request, before Django decides which
92+
view to execute.
7093

71-
``process_request()`` should return either ``None`` or an
72-
:class:`~django.http.HttpResponse` object. If it returns ``None``, Django will
73-
continue processing this request, executing any other middleware and, then, the
74-
appropriate view. If it returns an :class:`~django.http.HttpResponse` object,
75-
Django won't bother calling ANY other request, view or exception middleware, or
76-
the appropriate view; it'll return that :class:`~django.http.HttpResponse`.
77-
Response middleware is always called on every response.
94+
It should return either ``None`` or an :class:`~django.http.HttpResponse`
95+
object. If it returns ``None``, Django will continue processing this request,
96+
executing any other ``process_request()`` middleware, then, ``process_view()``
97+
middleware, and finally, the appropriate view. If it returns an
98+
:class:`~django.http.HttpResponse` object, Django won't bother calling any
99+
other request, view or exception middleware, or the appropriate view; it'll
100+
apply response middleware to that :class:`~django.http.HttpResponse`, and
101+
return the result.
78102

79103
.. _view-middleware:
80104

@@ -91,14 +115,15 @@ dictionary of keyword arguments that will be passed to the view. Neither
91115
``view_args`` nor ``view_kwargs`` include the first view argument
92116
(``request``).
93117

94-
``process_view()`` is called just before Django calls the view. It should
95-
return either ``None`` or an :class:`~django.http.HttpResponse` object. If it
96-
returns ``None``, Django will continue processing this request, executing any
97-
other ``process_view()`` middleware and, then, the appropriate view. If it
98-
returns an :class:`~django.http.HttpResponse` object, Django won't bother
99-
calling ANY other request, view or exception middleware, or the appropriate
100-
view; it'll return that :class:`~django.http.HttpResponse`. Response
101-
middleware is always called on every response.
118+
``process_view()`` is called just before Django calls the view.
119+
120+
It should return either ``None`` or an :class:`~django.http.HttpResponse`
121+
object. If it returns ``None``, Django will continue processing this request,
122+
executing any other ``process_view()`` middleware and, then, the appropriate
123+
view. If it returns an :class:`~django.http.HttpResponse` object, Django won't
124+
bother calling any other view or exception middleware, or the appropriate
125+
view; it'll apply response middleware to that
126+
:class:`~django.http.HttpResponse`, and return the result.
102127

103128
.. note::
104129

@@ -122,27 +147,25 @@ middleware is always called on every response.
122147

123148
.. method:: process_template_response(self, request, response)
124149

125-
``request`` is an :class:`~django.http.HttpRequest` object. ``response`` is a
126-
subclass of :class:`~django.template.response.SimpleTemplateResponse` (e.g.
127-
:class:`~django.template.response.TemplateResponse`) or any response object
128-
that implements a ``render`` method.
150+
``request`` is an :class:`~django.http.HttpRequest` object. ``response`` is
151+
the :class:`~django.template.response.TemplateResponse` object (or equivalent)
152+
returned by a Django view or by a middleware.
129153

130-
``process_template_response()`` must return a response object that implements a
131-
``render`` method. It could alter the given ``response`` by changing
132-
``response.template_name`` and ``response.context_data``, or it could create
133-
and return a brand-new
134-
:class:`~django.template.response.SimpleTemplateResponse` or equivalent.
154+
``process_template_response()`` is called just after the view has finished
155+
executing, if the response instance has a ``render()`` method, indicating that
156+
it is a :class:`~django.template.response.TemplateResponse` or equivalent.
135157

136-
``process_template_response()`` will only be called if the response
137-
instance has a ``render()`` method, indicating that it is a
158+
It must return a response object that implements a ``render`` method. It could
159+
alter the given ``response`` by changing ``response.template_name`` and
160+
``response.context_data``, or it could create and return a brand-new
138161
:class:`~django.template.response.TemplateResponse` or equivalent.
139162

140163
You don't need to explicitly render responses -- responses will be
141164
automatically rendered once all template response middleware has been
142165
called.
143166

144167
Middleware are run in reverse order during the response phase, which
145-
includes process_template_response.
168+
includes ``process_template_response()``.
146169

147170
.. _response-middleware:
148171

@@ -151,21 +174,34 @@ includes process_template_response.
151174

152175
.. method:: process_response(self, request, response)
153176

154-
``request`` is an :class:`~django.http.HttpRequest` object. ``response`` is the
155-
:class:`~django.http.HttpResponse` object returned by a Django view.
177+
``request`` is an :class:`~django.http.HttpRequest` object. ``response`` is
178+
the :class:`~django.http.HttpResponse` or
179+
:class:`~django.http.StreamingHttpResponse` object returned by a Django view
180+
or by a middleware.
181+
182+
``process_response()`` is called on all responses before they're returned to
183+
the browser.
156184

157-
``process_response()`` must return an :class:`~django.http.HttpResponse`
158-
object. It could alter the given ``response``, or it could create and return a
159-
brand-new :class:`~django.http.HttpResponse`.
185+
It must return an :class:`~django.http.HttpResponse` or
186+
:class:`~django.http.StreamingHttpResponse` object. It could alter the given
187+
``response``, or it could create and return a brand-new
188+
:class:`~django.http.HttpResponse` or
189+
:class:`~django.http.StreamingHttpResponse`.
160190

161191
Unlike the ``process_request()`` and ``process_view()`` methods, the
162-
``process_response()`` method is always called, even if the ``process_request()``
163-
and ``process_view()`` methods of the same middleware class were skipped because
164-
an earlier middleware method returned an :class:`~django.http.HttpResponse`
165-
(this means that your ``process_response()`` method cannot rely on setup done in
166-
``process_request()``, for example). In addition, during the response phase the
167-
classes are applied in reverse order, from the bottom up. This means classes
168-
defined at the end of :setting:`MIDDLEWARE_CLASSES` will be run first.
192+
``process_response()`` method is always called, even if the
193+
``process_request()`` and ``process_view()`` methods of the same middleware
194+
class were skipped (because an earlier middleware method returned an
195+
:class:`~django.http.HttpResponse`). In particular, this means that your
196+
``process_response()`` method cannot rely on setup done in
197+
``process_request()``.
198+
199+
Finally, remember that during the response phase, middleware are applied in
200+
reverse order, from the bottom up. This means classes defined at the end of
201+
:setting:`MIDDLEWARE_CLASSES` will be run first.
202+
203+
Dealing with streaming responses
204+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
169205

170206
.. versionchanged:: 1.5
171207
``response`` may also be an :class:`~django.http.StreamingHttpResponse`
@@ -180,10 +216,17 @@ must test for streaming responses and adjust their behavior accordingly::
180216
if response.streaming:
181217
response.streaming_content = wrap_streaming_content(response.streaming_content)
182218
else:
183-
response.content = wrap_content(response.content)
219+
response.content = alter_content(response.content)
220+
221+
.. note::
222+
223+
``streaming_content`` should be assumed to be too large to hold in memory.
224+
Response middleware may wrap it in a new generator, but must not consume
225+
it. Wrapping is typically implemented as follows::
184226

185-
``streaming_content`` should be assumed to be too large to hold in memory.
186-
Middleware may wrap it in a new generator, but must not consume it.
227+
def wrap_streaming_content(content)
228+
for chunk in content:
229+
yield alter_content(chunk)
187230

188231
.. _exception-middleware:
189232

@@ -198,8 +241,9 @@ Middleware may wrap it in a new generator, but must not consume it.
198241
Django calls ``process_exception()`` when a view raises an exception.
199242
``process_exception()`` should return either ``None`` or an
200243
:class:`~django.http.HttpResponse` object. If it returns an
201-
:class:`~django.http.HttpResponse` object, the response will be returned to
202-
the browser. Otherwise, default exception handling kicks in.
244+
:class:`~django.http.HttpResponse` object, the template response and response
245+
middleware will be applied, and the resulting response returned to the
246+
browser. Otherwise, default exception handling kicks in.
203247

204248
Again, middleware are run in reverse order during the response phase, which
205249
includes ``process_exception``. If an exception middleware returns a response,
@@ -224,9 +268,9 @@ Marking middleware as unused
224268
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
225269

226270
It's sometimes useful to determine at run-time whether a piece of middleware
227-
should be used. In these cases, your middleware's ``__init__`` method may raise
228-
``django.core.exceptions.MiddlewareNotUsed``. Django will then remove that
229-
piece of middleware from the middleware process.
271+
should be used. In these cases, your middleware's ``__init__`` method may
272+
raise :exc:`django.core.exceptions.MiddlewareNotUsed`. Django will then remove
273+
that piece of middleware from the middleware process.
230274

231275
Guidelines
232276
----------

0 commit comments

Comments
 (0)