- fr
- Language: en
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 or output.
Each middleware component is responsible for doing some specific function. For
example, Django includes a middleware component,
AuthenticationMiddleware
, that
associates users with requests using sessions.
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 built-in middleware reference.
Activating middleware¶
To activate a middleware component, add it to the
MIDDLEWARE_CLASSES
tuple 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 value created by django-admin startproject
:
MIDDLEWARE_CLASSES = (
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
A Django installation doesn’t require any middleware —
MIDDLEWARE_CLASSES
can be empty, if you’d like — but it’s strongly
suggested that you at least use
CommonMiddleware
.
The order in MIDDLEWARE_CLASSES
matters because a middleware can
depend on other middleware. For instance,
AuthenticationMiddleware
stores the
authenticated user in the session; therefore, it must run after
SessionMiddleware
. See
Middleware ordering for some common hints about ordering of Django
middleware classes.
Hooks and application order¶
During the request phase, before calling the view, Django applies middleware
in the order it’s defined in MIDDLEWARE_CLASSES
, top-down. Two
hooks are available:
During the response phase, after calling the view, middleware are applied in reverse order, from the bottom up. Three hooks are available:
process_exception()
(only if the view raised an exception)process_template_response()
(only for template responses)process_response()
If you prefer, you can also think of it like an onion: each middleware class is a “layer” that wraps the view.
The behavior of each hook is described below.
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
¶
-
process_request
(request)¶
request
is an HttpRequest
object.
process_request()
is called on each request, before Django decides which
view to execute.
It should return either None
or an HttpResponse
object. If it returns None
, Django will continue processing this request,
executing any other process_request()
middleware, then, process_view()
middleware, and finally, 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
apply response middleware to that HttpResponse
, and
return the result.
process_view
¶
-
process_view
(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 view or exception middleware, or the appropriate
view; it’ll apply response middleware to that
HttpResponse
, and return the result.
Note
Accessing request.POST
or
request.REQUEST
inside middleware
from process_request
or process_view
will prevent any view running
after the middleware from being able to modify the upload handlers
for the request, and should
normally be avoided.
The CsrfViewMiddleware
class can be
considered an exception, as it provides the
csrf_exempt()
and
csrf_protect()
decorators which allow
views to explicitly control at what point the CSRF validation should occur.
process_template_response
¶
-
process_template_response
(request, response)¶
request
is an HttpRequest
object. response
is
the TemplateResponse
object (or equivalent)
returned by a Django view or by a middleware.
process_template_response()
is called just after the view has finished
executing, if the response instance has a render()
method, indicating that
it is a TemplateResponse
or equivalent.
It must return a response object that implements a render
method. It could
alter the given response
by changing response.template_name
and
response.context_data
, or it could create and return a brand-new
TemplateResponse
or equivalent.
You don’t need to explicitly render responses – responses will be automatically rendered once all template response middleware has been called.
Middleware are run in reverse order during the response phase, which
includes process_template_response()
.
process_response
¶
-
process_response
(request, response)¶
request
is an HttpRequest
object. response
is
the HttpResponse
or
StreamingHttpResponse
object returned by a Django view
or by a middleware.
process_response()
is called on all responses before they’re returned to
the browser.
It must return an HttpResponse
or
StreamingHttpResponse
object. It could alter the given
response
, or it could create and return a brand-new
HttpResponse
or
StreamingHttpResponse
.
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
HttpResponse
). In particular, this means that your
process_response()
method cannot rely on setup done in
process_request()
.
Finally, remember that during the response phase, middleware are applied in
reverse order, from the bottom up. This means classes defined at the end of
MIDDLEWARE_CLASSES
will be run first.
Dealing with streaming responses¶
Unlike HttpResponse
,
StreamingHttpResponse
does not have a content
attribute. As a result, middleware can no longer assume that all responses
will have a content
attribute. If they need access to the content, they
must test for streaming responses and adjust their behavior accordingly:
if response.streaming:
response.streaming_content = wrap_streaming_content(response.streaming_content)
else:
response.content = alter_content(response.content)
Note
streaming_content
should be assumed to be too large to hold in memory.
Response middleware may wrap it in a new generator, but must not consume
it. Wrapping is typically implemented as follows:
def wrap_streaming_content(content):
for chunk in content:
yield alter_content(chunk)
process_exception
¶
-
process_exception
(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 template response and response
middleware will be applied, and the resulting response 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 returns 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 responds to the first request.
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 and a debug message will
be logged to the django.request
logger when DEBUG
is set to
True
.
Previously, MiddlewareNotUsed
exceptions
weren’t logged.
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.
- 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.