mirror of
				https://github.com/django/django.git
				synced 2025-10-25 14:46:09 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			367 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			367 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| ==========
 | |
| 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,
 | |
| :class:`~django.contrib.auth.middleware.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 :doc:`built-in
 | |
| middleware reference </ref/middleware>`.
 | |
| 
 | |
| .. versionchanged:: 1.10
 | |
| 
 | |
|     A new style of middleware was introduced for use with the new
 | |
|     :setting:`MIDDLEWARE` setting. If you're using the old
 | |
|     :setting:`MIDDLEWARE_CLASSES` setting, you'll need to :ref:`adapt old,
 | |
|     custom middleware <upgrading-middleware>` before using the new setting.
 | |
|     This document describes new-style middleware. Refer to this page in older
 | |
|     versions of the documentation for a description of how old-style middleware
 | |
|     works.
 | |
| 
 | |
| Writing your own middleware
 | |
| ===========================
 | |
| 
 | |
| A middleware factory is a callable that takes a ``get_response`` callable and
 | |
| returns a middleware. A middleware is a callable that takes a request and
 | |
| returns a response, just like a view.
 | |
| 
 | |
| A middleware can be written as a function that looks like this::
 | |
| 
 | |
|     def simple_middleware(get_response):
 | |
|         # One-time configuration and initialization.
 | |
| 
 | |
|         def middleware(request):
 | |
|             # Code to be executed for each request before
 | |
|             # the view (and later middleware) are called.
 | |
| 
 | |
|             response = get_response(request)
 | |
| 
 | |
|             # Code to be executed for each request/response after
 | |
|             # the view is called.
 | |
| 
 | |
|             return response
 | |
| 
 | |
|         return middleware
 | |
| 
 | |
| Or it can be written as a class whose instances are callable, like this::
 | |
| 
 | |
|     class SimpleMiddleware(object):
 | |
|         def __init__(self, get_response):
 | |
|             self.get_response = get_response
 | |
|             # One-time configuration and initialization.
 | |
| 
 | |
|         def __call__(self, request):
 | |
|             # Code to be executed for each request before
 | |
|             # the view (and later middleware) are called.
 | |
| 
 | |
|             response = self.get_response(request)
 | |
| 
 | |
|             # Code to be executed for each request/response after
 | |
|             # the view is called.
 | |
| 
 | |
|             return response
 | |
| 
 | |
| The ``get_response`` callable provided by Django might be the actual view (if
 | |
| this is the last listed middleware) or it might be the next middleware in the
 | |
| chain. The current middleware doesn't need to know or care what exactly it is,
 | |
| just that it represents whatever comes next.
 | |
| 
 | |
| The above is a slight simplification -- the ``get_response`` callable for the
 | |
| last middleware in the chain won't be the actual view but rather a wrapper
 | |
| method from the handler which takes care of applying :ref:`view middleware
 | |
| <view-middleware>`, calling the view with appropriate URL arguments, and
 | |
| applying :ref:`template-response <template-response-middleware>` and
 | |
| :ref:`exception <exception-middleware>` middleware.
 | |
| 
 | |
| Middleware can live anywhere on your Python path.
 | |
| 
 | |
| ``__init__(get_response)``
 | |
| --------------------------
 | |
| 
 | |
| Middleware factories must accept a ``get_response`` argument. You can also
 | |
| initialize some global state for the middleware. Keep in mind a couple of
 | |
| caveats:
 | |
| 
 | |
| * Django initializes your middleware with only the ``get_response`` argument,
 | |
|   so you can't define ``__init__()`` as requiring any other arguments.
 | |
| 
 | |
| * Unlike the ``__call__()`` method which is called once per request,
 | |
|   ``__init__()`` is called only *once*, when the Web server starts.
 | |
| 
 | |
| .. versionchanged:: 1.10
 | |
| 
 | |
|     In older versions, ``__init__()`` wasn't called until the Web server
 | |
|     responded to its first request.
 | |
| 
 | |
|     In older versions, ``__init__()`` didn't accept any arguments. To allow
 | |
|     your middleware to be used in Django 1.9 and earlier, make ``get_response``
 | |
|     an optional argument (``get_response=None``).
 | |
| 
 | |
| Marking middleware as unused
 | |
| ----------------------------
 | |
| 
 | |
| It's sometimes useful to determine at startup time whether a piece of
 | |
| middleware should be used. In these cases, your middleware's ``__init__()``
 | |
| method may raise :exc:`~django.core.exceptions.MiddlewareNotUsed`. Django will
 | |
| then remove that middleware from the middleware process and log a debug message
 | |
| to the :ref:`django-request-logger` logger when :setting:`DEBUG` is ``True``.
 | |
| 
 | |
| Activating middleware
 | |
| =====================
 | |
| 
 | |
| To activate a middleware component, add it to the :setting:`MIDDLEWARE` list in
 | |
| your Django settings.
 | |
| 
 | |
| In :setting:`MIDDLEWARE`, each middleware component is represented by a string:
 | |
| the full Python path to the middleware factory's class or function name. For
 | |
| example, here's the default value created by :djadmin:`django-admin
 | |
| startproject <startproject>`::
 | |
| 
 | |
|     MIDDLEWARE = [
 | |
|         'django.middleware.security.SecurityMiddleware',
 | |
|         'django.contrib.sessions.middleware.SessionMiddleware',
 | |
|         'django.middleware.common.CommonMiddleware',
 | |
|         'django.middleware.csrf.CsrfViewMiddleware',
 | |
|         'django.contrib.auth.middleware.AuthenticationMiddleware',
 | |
|         'django.contrib.messages.middleware.MessageMiddleware',
 | |
|         'django.middleware.clickjacking.XFrameOptionsMiddleware',
 | |
|     ]
 | |
| 
 | |
| A Django installation doesn't require any middleware — :setting:`MIDDLEWARE`
 | |
| can be empty, if you'd like — but it's strongly suggested that you at least use
 | |
| :class:`~django.middleware.common.CommonMiddleware`.
 | |
| 
 | |
| The order in :setting:`MIDDLEWARE` matters because a middleware can depend on
 | |
| other middleware. For instance,
 | |
| :class:`~django.contrib.auth.middleware.AuthenticationMiddleware` stores the
 | |
| authenticated user in the session; therefore, it must run after
 | |
| :class:`~django.contrib.sessions.middleware.SessionMiddleware`. See
 | |
| :ref:`middleware-ordering` for some common hints about ordering of Django
 | |
| middleware classes.
 | |
| 
 | |
| Middleware order and layering
 | |
| =============================
 | |
| 
 | |
| During the request phase, before calling the view, Django applies middleware in
 | |
| the order it's defined in :setting:`MIDDLEWARE`, top-down.
 | |
| 
 | |
| You can think of it like an onion: each middleware class is a "layer" that
 | |
| wraps the view, which is in the core of the onion. If the request passes
 | |
| through all the layers of the onion (each one calls ``get_response`` to pass
 | |
| the request in to the next layer), all the way to the view at the core, the
 | |
| response will then pass through every layer (in reverse order) on the way back
 | |
| out.
 | |
| 
 | |
| If one of the layers decides to short-circuit and return a response without
 | |
| ever calling its ``get_response``, none of the layers of the onion inside that
 | |
| layer (including the view) will see the request or the response. The response
 | |
| will only return through the same layers that the request passed in through.
 | |
| 
 | |
| Other middleware hooks
 | |
| ======================
 | |
| 
 | |
| Besides the basic request/response middleware pattern described earlier, you
 | |
| can add three other special methods to class-based middleware:
 | |
| 
 | |
| .. _view-middleware:
 | |
| 
 | |
| ``process_view()``
 | |
| ------------------
 | |
| 
 | |
| .. method:: process_view(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 the appropriate view; it'll apply response middleware to that
 | |
| :class:`~django.http.HttpResponse` and return the result.
 | |
| 
 | |
| .. note::
 | |
| 
 | |
|     Accessing :attr:`request.POST <django.http.HttpRequest.POST>` inside
 | |
|     middleware before the view runs or in ``process_view()`` will prevent any
 | |
|     view running after the middleware from being able to :ref:`modify the
 | |
|     upload handlers for the request <modifying_upload_handlers_on_the_fly>`,
 | |
|     and should normally be avoided.
 | |
| 
 | |
|     The :class:`~django.middleware.csrf.CsrfViewMiddleware` class can be
 | |
|     considered an exception, as it provides the
 | |
|     :func:`~django.views.decorators.csrf.csrf_exempt` and
 | |
|     :func:`~django.views.decorators.csrf.csrf_protect` decorators which allow
 | |
|     views to explicitly control at what point the CSRF validation should occur.
 | |
| 
 | |
| .. _exception-middleware:
 | |
| 
 | |
| ``process_exception()``
 | |
| -----------------------
 | |
| 
 | |
| .. method:: process_exception(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 template response and response
 | |
| middleware will be applied and the resulting response returned to the
 | |
| browser. Otherwise, :ref:`default exception handling <error-views>` 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 ``process_exception`` methods of the middleware classes above that
 | |
| middleware won't be called at all.
 | |
| 
 | |
| .. _template-response-middleware:
 | |
| 
 | |
| ``process_template_response()``
 | |
| -------------------------------
 | |
| 
 | |
| .. method:: process_template_response(request, response)
 | |
| 
 | |
| ``request`` is an :class:`~django.http.HttpRequest` object. ``response`` is
 | |
| the :class:`~django.template.response.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 :class:`~django.template.response.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
 | |
| :class:`~django.template.response.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()``.
 | |
| 
 | |
| Dealing with streaming responses
 | |
| ================================
 | |
| 
 | |
| Unlike :class:`~django.http.HttpResponse`,
 | |
| :class:`~django.http.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)
 | |
| 
 | |
| Exception handling
 | |
| ==================
 | |
| 
 | |
| Django automatically converts exceptions raised by the view or by middleware
 | |
| into an appropriate HTTP response with an error status code. :ref:`Certain
 | |
| exceptions <error-views>` are converted to 4xx status codes, while an unknown
 | |
| exception is converted to a 500 status code.
 | |
| 
 | |
| This conversion takes place before and after each middleware (you can think of
 | |
| it as the thin film in between each layer of the onion), so that every
 | |
| middleware can always rely on getting some kind of HTTP response back from
 | |
| calling its ``get_response`` callable. Middleware don't need to worry about
 | |
| wrapping their call to ``get_response`` in a ``try/except`` and handling an
 | |
| exception that might have been raised by a later middleware or the view. Even
 | |
| if the very next middleware in the chain raises an
 | |
| :class:`~django.http.Http404` exception, for example, your middleware won't see
 | |
| that exception; instead it will get an :class:`~django.http.HttpResponse`
 | |
| object with a :attr:`~django.http.HttpResponse.status_code` of 404.
 | |
| 
 | |
| .. _upgrading-middleware:
 | |
| 
 | |
| Upgrading pre-Django 1.10-style middleware
 | |
| ==========================================
 | |
| 
 | |
| .. class:: django.utils.deprecation.MiddlewareMixin
 | |
|     :module:
 | |
| 
 | |
| Django provides ``django.utils.deprecation.MiddlewareMixin`` to ease creating
 | |
| middleware classes that are compatible with both :setting:`MIDDLEWARE` and the
 | |
| old :setting:`MIDDLEWARE_CLASSES`. All middleware classes included with Django
 | |
| are compatible with both settings.
 | |
| 
 | |
| The mixin provides an ``__init__()`` method that accepts an optional
 | |
| ``get_response`` argument and stores it in ``self.get_response``.
 | |
| 
 | |
| The ``__call__()`` method:
 | |
| 
 | |
| #. Calls ``self.process_request(request)`` (if defined).
 | |
| #. Calls ``self.get_response(request)`` to get the response from later
 | |
|    middleware and the view.
 | |
| #. Calls ``self.process_response(request, response)`` (if defined).
 | |
| #. Returns the response.
 | |
| 
 | |
| If used with :setting:`MIDDLEWARE_CLASSES`, the ``__call__()`` method will
 | |
| never be used; Django calls ``process_request()`` and ``process_response()``
 | |
| directly.
 | |
| 
 | |
| In most cases, inheriting from this mixin will be sufficient to make an
 | |
| old-style middleware compatible with the new system with sufficient
 | |
| backwards-compatibility. The new short-circuiting semantics will be harmless or
 | |
| even beneficial to the existing middleware. In a few cases, a middleware class
 | |
| may need some changes to adjust to the new semantics.
 | |
| 
 | |
| These are the behavioral differences between using :setting:`MIDDLEWARE` and
 | |
| :setting:`MIDDLEWARE_CLASSES`:
 | |
| 
 | |
| 1. Under :setting:`MIDDLEWARE_CLASSES`, every middleware will always have its
 | |
|    ``process_response`` method called, even if an earlier middleware
 | |
|    short-circuited by returning a response from its ``process_request``
 | |
|    method. Under :setting:`MIDDLEWARE`, middleware behaves more like an onion:
 | |
|    the layers that a response goes through on the way out are the same layers
 | |
|    that saw the request on the way in. If a middleware short-circuits, only
 | |
|    that middleware and the ones before it in :setting:`MIDDLEWARE` will see the
 | |
|    response.
 | |
| 
 | |
| 2. Under :setting:`MIDDLEWARE_CLASSES`, ``process_exception`` is applied to
 | |
|    exceptions raised from a middleware ``process_request`` method. Under
 | |
|    :setting:`MIDDLEWARE`, ``process_exception`` applies only to exceptions
 | |
|    raised from the view (or from the ``render`` method of a
 | |
|    :class:`~django.template.response.TemplateResponse`). Exceptions raised from
 | |
|    a middleware are converted to the appropriate HTTP response and then passed
 | |
|    to the next middleware.
 | |
| 
 | |
| 3. Under :setting:`MIDDLEWARE_CLASSES`, if a ``process_response`` method raises
 | |
|    an exception, the ``process_response`` methods of all earlier middleware are
 | |
|    skipped and a ``500 Internal Server Error`` HTTP response is always
 | |
|    returned (even if the exception raised was e.g. an
 | |
|    :class:`~django.http.Http404`). Under :setting:`MIDDLEWARE`, an exception
 | |
|    raised from a middleware will immediately be converted to the appropriate
 | |
|    HTTP response, and then the next middleware in line will see that
 | |
|    response. Middleware are never skipped due to a middleware raising an
 | |
|    exception.
 |