mirror of
				https://github.com/django/django.git
				synced 2025-10-26 07:06:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			527 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			527 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| ==========
 | |
| Middleware
 | |
| ==========
 | |
| 
 | |
| .. module:: django.middleware
 | |
|    :synopsis: Django's built-in middleware classes.
 | |
| 
 | |
| This document explains all middleware components that come with Django. For
 | |
| information on how to use them and how to write your own middleware, see
 | |
| the :doc:`middleware usage guide </topics/http/middleware>`.
 | |
| 
 | |
| Available middleware
 | |
| ====================
 | |
| 
 | |
| Cache middleware
 | |
| ----------------
 | |
| 
 | |
| .. module:: django.middleware.cache
 | |
|    :synopsis: Middleware for the site-wide cache.
 | |
| 
 | |
| .. class:: UpdateCacheMiddleware
 | |
| 
 | |
| .. class:: FetchFromCacheMiddleware
 | |
| 
 | |
| Enable the site-wide cache. If these are enabled, each Django-powered page will
 | |
| be cached for as long as the :setting:`CACHE_MIDDLEWARE_SECONDS` setting
 | |
| defines. See the :doc:`cache documentation </topics/cache>`.
 | |
| 
 | |
| "Common" middleware
 | |
| -------------------
 | |
| 
 | |
| .. module:: django.middleware.common
 | |
|    :synopsis: Middleware adding "common" conveniences for perfectionists.
 | |
| 
 | |
| .. class:: CommonMiddleware
 | |
| 
 | |
| Adds a few conveniences for perfectionists:
 | |
| 
 | |
| * Forbids access to user agents in the :setting:`DISALLOWED_USER_AGENTS`
 | |
|   setting, which should be a list of compiled regular expression objects.
 | |
| 
 | |
| * Performs URL rewriting based on the :setting:`APPEND_SLASH` and
 | |
|   :setting:`PREPEND_WWW` settings.
 | |
| 
 | |
|   If :setting:`APPEND_SLASH` is ``True`` and the initial URL doesn't end
 | |
|   with a slash, and it is not found in the URLconf, then a new URL is
 | |
|   formed by appending a slash at the end. If this new URL is found in the
 | |
|   URLconf, then Django redirects the request to this new URL. Otherwise,
 | |
|   the initial URL is processed as usual.
 | |
| 
 | |
|   For example, ``foo.com/bar`` will be redirected to ``foo.com/bar/`` if
 | |
|   you don't have a valid URL pattern for ``foo.com/bar`` but *do* have a
 | |
|   valid pattern for ``foo.com/bar/``.
 | |
| 
 | |
|   If :setting:`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 :setting:`USE_ETAGS` setting. If
 | |
|   :setting:`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.
 | |
| 
 | |
| * Sets the ``Content-Length`` header for non-streaming responses.
 | |
| 
 | |
| .. versionchanged:: 1.11
 | |
| 
 | |
|     Older versions didn't set the ``Content-Length`` header.
 | |
| 
 | |
| .. deprecated:: 1.11
 | |
| 
 | |
|     The :setting:`USE_ETAGS` setting is deprecated in favor of using
 | |
|     :class:`~django.middleware.http.ConditionalGetMiddleware` for ETag
 | |
|     processing.
 | |
| 
 | |
| .. attribute:: CommonMiddleware.response_redirect_class
 | |
| 
 | |
| Defaults to :class:`~django.http.HttpResponsePermanentRedirect`. Subclass
 | |
| ``CommonMiddleware`` and override the attribute to customize the redirects
 | |
| issued by the middleware.
 | |
| 
 | |
| .. class:: BrokenLinkEmailsMiddleware
 | |
| 
 | |
| * Sends broken link notification emails to :setting:`MANAGERS` (see
 | |
|   :doc:`/howto/error-reporting`).
 | |
| 
 | |
| Exception middleware
 | |
| --------------------
 | |
| 
 | |
| .. module:: django.middleware.exception
 | |
|    :synopsis: Middleware to return responses for exceptions.
 | |
| 
 | |
| .. class:: ExceptionMiddleware
 | |
| 
 | |
| Catches exceptions raised during the request/response cycle and returns the
 | |
| appropriate response.
 | |
| 
 | |
| * :class:`~django.http.Http404` is processed by
 | |
|   :data:`~django.conf.urls.handler404` (or a more friendly debug page if
 | |
|   :setting:`DEBUG=True <DEBUG>`).
 | |
| * :class:`~django.core.exceptions.PermissionDenied` is processed
 | |
|   by :data:`~django.conf.urls.handler403`.
 | |
| * ``MultiPartParserError`` is processed by :data:`~django.conf.urls.handler400`.
 | |
| * :class:`~django.core.exceptions.SuspiciousOperation` is processed by
 | |
|   :data:`~django.conf.urls.handler400`  (or a more friendly debug page if
 | |
|   :setting:`DEBUG=True <DEBUG>`).
 | |
| * Any other exception is processed by :data:`~django.conf.urls.handler500`
 | |
|   (or a more friendly debug page if :setting:`DEBUG=True <DEBUG>`).
 | |
| 
 | |
| Django uses this middleware regardless of whether or not you include it in
 | |
| :setting:`MIDDLEWARE`, however, you may want to subclass if your own middleware
 | |
| needs to transform any of these exceptions into the appropriate responses.
 | |
| :class:`~django.middleware.locale.LocaleMiddleware` does this, for example.
 | |
| 
 | |
| GZip middleware
 | |
| ---------------
 | |
| 
 | |
| .. module:: django.middleware.gzip
 | |
|    :synopsis: Middleware to serve GZipped content for performance.
 | |
| 
 | |
| .. class:: GZipMiddleware
 | |
| 
 | |
| .. warning::
 | |
| 
 | |
|     Security researchers recently revealed that when compression techniques
 | |
|     (including ``GZipMiddleware``) are used on a website, the site may become
 | |
|     exposed to a number of possible attacks. Before using ``GZipMiddleware`` on
 | |
|     your site, you should consider very carefully whether you are subject to
 | |
|     these attacks. If you're in *any* doubt about whether you're affected, you
 | |
|     should avoid using ``GZipMiddleware``. For more details, see the `the BREACH
 | |
|     paper (PDF)`_ and `breachattack.com`_.
 | |
| 
 | |
|     .. _the BREACH paper (PDF): http://breachattack.com/resources/BREACH%20-%20SSL,%20gone%20in%2030%20seconds.pdf
 | |
|     .. _breachattack.com: http://breachattack.com
 | |
| 
 | |
| Compresses content for browsers that understand GZip compression (all modern
 | |
| browsers).
 | |
| 
 | |
| This middleware should be placed before any other middleware that need to
 | |
| read or write the response body so that compression happens afterward.
 | |
| 
 | |
| It will NOT compress content if any of the following are true:
 | |
| 
 | |
| * The content body is less than 200 bytes long.
 | |
| 
 | |
| * The response has already set the ``Content-Encoding`` header.
 | |
| 
 | |
| * The request (the browser) hasn't sent an ``Accept-Encoding`` header
 | |
|   containing ``gzip``.
 | |
| 
 | |
| If the response has an ``ETag`` header, the ETag is made weak to comply with
 | |
| :rfc:`7232#section-2.1`.
 | |
| 
 | |
| You can apply GZip compression to individual views using the
 | |
| :func:`~django.views.decorators.gzip.gzip_page()` decorator.
 | |
| 
 | |
| Conditional GET middleware
 | |
| --------------------------
 | |
| 
 | |
| .. module:: django.middleware.http
 | |
|    :synopsis: Middleware handling advanced HTTP features.
 | |
| 
 | |
| .. class:: ConditionalGetMiddleware
 | |
| 
 | |
| Handles conditional GET operations. If the response doesn't have an ``ETag``
 | |
| header, the middleware adds one if needed. 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
 | |
| :class:`~django.http.HttpResponseNotModified`.
 | |
| 
 | |
| .. versionchanged:: 1.11
 | |
| 
 | |
|     In older versions, the middleware set the ``Content-Length`` and ``Date``
 | |
|     headers and didn't set the ``ETag`` header.
 | |
| 
 | |
| Locale middleware
 | |
| -----------------
 | |
| 
 | |
| .. module:: django.middleware.locale
 | |
|    :synopsis: Middleware to enable language selection based on the request.
 | |
| 
 | |
| .. class:: LocaleMiddleware
 | |
| 
 | |
| Enables language selection based on data from the request. It customizes
 | |
| content for each user. See the :doc:`internationalization documentation
 | |
| </topics/i18n/translation>`.
 | |
| 
 | |
| .. attribute:: LocaleMiddleware.response_redirect_class
 | |
| 
 | |
| Defaults to :class:`~django.http.HttpResponseRedirect`. Subclass
 | |
| ``LocaleMiddleware`` and override the attribute to customize the redirects
 | |
| issued by the middleware.
 | |
| 
 | |
| Message middleware
 | |
| ------------------
 | |
| 
 | |
| .. module:: django.contrib.messages.middleware
 | |
|    :synopsis: Message middleware.
 | |
| 
 | |
| .. class:: MessageMiddleware
 | |
| 
 | |
| Enables cookie- and session-based message support. See the
 | |
| :doc:`messages documentation </ref/contrib/messages>`.
 | |
| 
 | |
| .. _security-middleware:
 | |
| 
 | |
| Security middleware
 | |
| -------------------
 | |
| 
 | |
| .. module:: django.middleware.security
 | |
|     :synopsis: Security middleware.
 | |
| 
 | |
| .. warning::
 | |
|     If your deployment situation allows, it's usually a good idea to have your
 | |
|     front-end Web server perform the functionality provided by the
 | |
|     ``SecurityMiddleware``. That way, if there are requests that aren't served
 | |
|     by Django (such as static media or user-uploaded files), they will have
 | |
|     the same protections as requests to your Django application.
 | |
| 
 | |
| .. class:: SecurityMiddleware
 | |
| 
 | |
| The ``django.middleware.security.SecurityMiddleware`` provides several security
 | |
| enhancements to the request/response cycle. Each one can be independently
 | |
| enabled or disabled with a setting.
 | |
| 
 | |
| * :setting:`SECURE_BROWSER_XSS_FILTER`
 | |
| * :setting:`SECURE_CONTENT_TYPE_NOSNIFF`
 | |
| * :setting:`SECURE_HSTS_INCLUDE_SUBDOMAINS`
 | |
| * :setting:`SECURE_HSTS_PRELOAD`
 | |
| * :setting:`SECURE_HSTS_SECONDS`
 | |
| * :setting:`SECURE_REDIRECT_EXEMPT`
 | |
| * :setting:`SECURE_SSL_HOST`
 | |
| * :setting:`SECURE_SSL_REDIRECT`
 | |
| 
 | |
| .. _http-strict-transport-security:
 | |
| 
 | |
| HTTP Strict Transport Security
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| For sites that should only be accessed over HTTPS, you can instruct modern
 | |
| browsers to refuse to connect to your domain name via an insecure connection
 | |
| (for a given period of time) by setting the `"Strict-Transport-Security"
 | |
| header`_. This reduces your exposure to some SSL-stripping man-in-the-middle
 | |
| (MITM) attacks.
 | |
| 
 | |
| ``SecurityMiddleware`` will set this header for you on all HTTPS responses if
 | |
| you set the :setting:`SECURE_HSTS_SECONDS` setting to a non-zero integer value.
 | |
| 
 | |
| When enabling HSTS, it's a good idea to first use a small value for testing,
 | |
| for example, :setting:`SECURE_HSTS_SECONDS = 3600<SECURE_HSTS_SECONDS>` for one
 | |
| hour. Each time a Web browser sees the HSTS header from your site, it will
 | |
| refuse to communicate non-securely (using HTTP) with your domain for the given
 | |
| period of time. Once you confirm that all assets are served securely on your
 | |
| site (i.e. HSTS didn't break anything), it's a good idea to increase this value
 | |
| so that infrequent visitors will be protected (31536000 seconds, i.e. 1 year,
 | |
| is common).
 | |
| 
 | |
| Additionally, if you set the :setting:`SECURE_HSTS_INCLUDE_SUBDOMAINS` setting
 | |
| to ``True``, ``SecurityMiddleware`` will add the ``includeSubDomains`` directive
 | |
| to the ``Strict-Transport-Security`` header. This is recommended (assuming all
 | |
| subdomains are served exclusively using HTTPS), otherwise your site may still
 | |
| be vulnerable via an insecure connection to a subdomain.
 | |
| 
 | |
| If you wish to submit your site to the `browser preload list`_, set the
 | |
| :setting:`SECURE_HSTS_PRELOAD` setting to ``True``. That appends the
 | |
| ``preload`` directive to the ``Strict-Transport-Security`` header.
 | |
| 
 | |
| .. warning::
 | |
|     The HSTS policy applies to your entire domain, not just the URL of the
 | |
|     response that you set the header on. Therefore, you should only use it if
 | |
|     your entire domain is served via HTTPS only.
 | |
| 
 | |
|     Browsers properly respecting the HSTS header will refuse to allow users to
 | |
|     bypass warnings and connect to a site with an expired, self-signed, or
 | |
|     otherwise invalid SSL certificate. If you use HSTS, make sure your
 | |
|     certificates are in good shape and stay that way!
 | |
| 
 | |
| .. note::
 | |
|     If you are deployed behind a load-balancer or reverse-proxy server, and the
 | |
|     ``Strict-Transport-Security`` header is not being added to your responses,
 | |
|     it may be because Django doesn't realize that it's on a secure connection;
 | |
|     you may need to set the :setting:`SECURE_PROXY_SSL_HEADER` setting.
 | |
| 
 | |
| .. _"Strict-Transport-Security" header: https://en.wikipedia.org/wiki/Strict_Transport_Security
 | |
| .. _browser preload list: https://hstspreload.org/
 | |
| 
 | |
| .. _x-content-type-options:
 | |
| 
 | |
| ``X-Content-Type-Options: nosniff``
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| Some browsers will try to guess the content types of the assets that they
 | |
| fetch, overriding the ``Content-Type`` header. While this can help display
 | |
| sites with improperly configured servers, it can also pose a security
 | |
| risk.
 | |
| 
 | |
| If your site serves user-uploaded files, a malicious user could upload a
 | |
| specially-crafted file that would be interpreted as HTML or JavaScript by
 | |
| the browser when you expected it to be something harmless.
 | |
| 
 | |
| To prevent the browser from guessing the content type and force it to
 | |
| always use the type provided in the ``Content-Type`` header, you can pass
 | |
| the `X-Content-Type-Options: nosniff`__ header.  ``SecurityMiddleware`` will
 | |
| do this for all responses if the :setting:`SECURE_CONTENT_TYPE_NOSNIFF` setting
 | |
| is ``True``.
 | |
| 
 | |
| Note that in most deployment situations where Django isn't involved in serving
 | |
| user-uploaded files, this setting won't help you. For example, if your
 | |
| :setting:`MEDIA_URL` is served directly by your front-end Web server (nginx,
 | |
| Apache, etc.) then you'd want to set this header there. On the other hand, if
 | |
| you are using Django to do something like require authorization in order to
 | |
| download files and you cannot set the header using your Web server, this
 | |
| setting will be useful.
 | |
| 
 | |
| __ https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
 | |
| 
 | |
| .. _x-xss-protection:
 | |
| 
 | |
| ``X-XSS-Protection: 1; mode=block``
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| Some browsers have the ability to block content that appears to be an `XSS
 | |
| attack`_. They work by looking for JavaScript content in the GET or POST
 | |
| parameters of a page. If the JavaScript is replayed in the server's response,
 | |
| the page is blocked from rendering and an error page is shown instead.
 | |
| 
 | |
| The `X-XSS-Protection header`_ is used to control the operation of the
 | |
| XSS filter.
 | |
| 
 | |
| To enable the XSS filter in the browser, and force it to always block
 | |
| suspected XSS attacks, you can pass the ``X-XSS-Protection: 1; mode=block``
 | |
| header. ``SecurityMiddleware`` will do this for all responses if the
 | |
| :setting:`SECURE_BROWSER_XSS_FILTER` setting is ``True``.
 | |
| 
 | |
| .. warning::
 | |
|     The browser XSS filter is a useful defense measure, but must not be
 | |
|     relied upon exclusively. It cannot detect all XSS attacks and not all
 | |
|     browsers support the header. Ensure you are still :ref:`validating and
 | |
|     sanitizing <cross-site-scripting>` all input to prevent XSS attacks.
 | |
| 
 | |
| .. _XSS attack: https://en.wikipedia.org/wiki/Cross-site_scripting
 | |
| .. _X-XSS-Protection header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
 | |
| 
 | |
| .. _ssl-redirect:
 | |
| 
 | |
| SSL Redirect
 | |
| ~~~~~~~~~~~~
 | |
| 
 | |
| If your site offers both HTTP and HTTPS connections, most users will end up
 | |
| with an unsecured connection by default. For best security, you should redirect
 | |
| all HTTP connections to HTTPS.
 | |
| 
 | |
| If you set the :setting:`SECURE_SSL_REDIRECT` setting to True,
 | |
| ``SecurityMiddleware`` will permanently (HTTP 301) redirect all HTTP
 | |
| connections to HTTPS.
 | |
| 
 | |
| .. note::
 | |
| 
 | |
|     For performance reasons, it's preferable to do these redirects outside of
 | |
|     Django, in a front-end load balancer or reverse-proxy server such as
 | |
|     `nginx`_. :setting:`SECURE_SSL_REDIRECT` is intended for the deployment
 | |
|     situations where this isn't an option.
 | |
| 
 | |
| If the :setting:`SECURE_SSL_HOST` setting has a value, all redirects will be
 | |
| sent to that host instead of the originally-requested host.
 | |
| 
 | |
| If there are a few pages on your site that should be available over HTTP, and
 | |
| not redirected to HTTPS, you can list regular expressions to match those URLs
 | |
| in the :setting:`SECURE_REDIRECT_EXEMPT` setting.
 | |
| 
 | |
| .. note::
 | |
|     If you are deployed behind a load-balancer or reverse-proxy server and
 | |
|     Django can't seem to tell when a request actually is already secure, you
 | |
|     may need to set the :setting:`SECURE_PROXY_SSL_HEADER` setting.
 | |
| 
 | |
| .. _nginx: http://nginx.org
 | |
| 
 | |
| Session middleware
 | |
| ------------------
 | |
| 
 | |
| .. module:: django.contrib.sessions.middleware
 | |
|    :synopsis: Session middleware.
 | |
| 
 | |
| .. class:: SessionMiddleware
 | |
| 
 | |
| Enables session support. See the :doc:`session documentation
 | |
| </topics/http/sessions>`.
 | |
| 
 | |
| Site middleware
 | |
| ---------------
 | |
| 
 | |
| .. module:: django.contrib.sites.middleware
 | |
|   :synopsis: Site middleware.
 | |
| 
 | |
| .. class:: CurrentSiteMiddleware
 | |
| 
 | |
| Adds the ``site`` attribute representing the current site to every incoming
 | |
| ``HttpRequest`` object. See the :ref:`sites documentation <site-middleware>`.
 | |
| 
 | |
| Authentication middleware
 | |
| -------------------------
 | |
| 
 | |
| .. module:: django.contrib.auth.middleware
 | |
|   :synopsis: Authentication middleware.
 | |
| 
 | |
| .. class:: AuthenticationMiddleware
 | |
| 
 | |
| Adds the ``user`` attribute, representing the currently-logged-in user, to
 | |
| every incoming ``HttpRequest`` object. See :ref:`Authentication in Web requests
 | |
| <auth-web-requests>`.
 | |
| 
 | |
| .. class:: RemoteUserMiddleware
 | |
| 
 | |
| Middleware for utilizing Web server provided authentication. See
 | |
| :doc:`/howto/auth-remote-user` for usage details.
 | |
| 
 | |
| .. class:: PersistentRemoteUserMiddleware
 | |
| 
 | |
| Middleware for utilizing Web server provided authentication when enabled only
 | |
| on the login page. See :ref:`persistent-remote-user-middleware-howto` for usage
 | |
| details.
 | |
| 
 | |
| CSRF protection middleware
 | |
| --------------------------
 | |
| 
 | |
| .. module:: django.middleware.csrf
 | |
|    :synopsis: Middleware adding protection against Cross Site Request
 | |
|               Forgeries.
 | |
| 
 | |
| .. class:: CsrfViewMiddleware
 | |
| 
 | |
| Adds protection against Cross Site Request Forgeries by adding hidden form
 | |
| fields to POST forms and checking requests for the correct value. See the
 | |
| :doc:`Cross Site Request Forgery protection documentation </ref/csrf>`.
 | |
| 
 | |
| ``X-Frame-Options`` middleware
 | |
| ------------------------------
 | |
| 
 | |
| .. module:: django.middleware.clickjacking
 | |
|    :synopsis: Clickjacking protection
 | |
| 
 | |
| .. class:: XFrameOptionsMiddleware
 | |
| 
 | |
| Simple :doc:`clickjacking protection via the X-Frame-Options header </ref/clickjacking/>`.
 | |
| 
 | |
| .. _middleware-ordering:
 | |
| 
 | |
| Middleware ordering
 | |
| ===================
 | |
| 
 | |
| Here are some hints about the ordering of various Django middleware classes:
 | |
| 
 | |
| #. :class:`~django.middleware.security.SecurityMiddleware`
 | |
| 
 | |
|    It should go near the top of the list if you're going to turn on the SSL
 | |
|    redirect as that avoids running through a bunch of other unnecessary
 | |
|    middleware.
 | |
| 
 | |
| #. :class:`~django.middleware.cache.UpdateCacheMiddleware`
 | |
| 
 | |
|    Before those that modify the ``Vary`` header (``SessionMiddleware``,
 | |
|    ``GZipMiddleware``, ``LocaleMiddleware``).
 | |
| 
 | |
| #. :class:`~django.middleware.gzip.GZipMiddleware`
 | |
| 
 | |
|    Before any middleware that may change or use the response body.
 | |
| 
 | |
|    After ``UpdateCacheMiddleware``: Modifies ``Vary`` header.
 | |
| 
 | |
| #. :class:`~django.middleware.http.ConditionalGetMiddleware`
 | |
| 
 | |
|    Before ``CommonMiddleware``: uses its ``ETag`` header when
 | |
|    :setting:`USE_ETAGS` = ``True``.
 | |
| 
 | |
| #. :class:`~django.contrib.sessions.middleware.SessionMiddleware`
 | |
| 
 | |
|    After ``UpdateCacheMiddleware``: Modifies ``Vary`` header.
 | |
| 
 | |
| #. :class:`~django.middleware.locale.LocaleMiddleware`
 | |
| 
 | |
|    One of the topmost, after ``SessionMiddleware`` (uses session data) and
 | |
|    ``UpdateCacheMiddleware`` (modifies ``Vary`` header).
 | |
| 
 | |
| #. :class:`~django.middleware.common.CommonMiddleware`
 | |
| 
 | |
|    Before any middleware that may change the response (it calculates ``ETags``).
 | |
| 
 | |
|    After ``GZipMiddleware`` so it won't calculate an ``ETag`` header on gzipped
 | |
|    contents.
 | |
| 
 | |
|    Close to the top: it redirects when :setting:`APPEND_SLASH` or
 | |
|    :setting:`PREPEND_WWW` are set to ``True``.
 | |
| 
 | |
| #. :class:`~django.middleware.csrf.CsrfViewMiddleware`
 | |
| 
 | |
|    Before any view middleware that assumes that CSRF attacks have been dealt
 | |
|    with.
 | |
| 
 | |
|    It must come after ``SessionMiddleware`` if you're using
 | |
|    :setting:`CSRF_USE_SESSIONS`.
 | |
| 
 | |
| #. :class:`~django.contrib.auth.middleware.AuthenticationMiddleware`
 | |
| 
 | |
|    After ``SessionMiddleware``: uses session storage.
 | |
| 
 | |
| #. :class:`~django.contrib.messages.middleware.MessageMiddleware`
 | |
| 
 | |
|    After ``SessionMiddleware``: can use session-based storage.
 | |
| 
 | |
| #. :class:`~django.middleware.cache.FetchFromCacheMiddleware`
 | |
| 
 | |
|    After any middleware that modifies the ``Vary`` header: that header is used
 | |
|    to pick a value for the cache hash-key.
 | |
| 
 | |
| #. :class:`~django.contrib.flatpages.middleware.FlatpageFallbackMiddleware`
 | |
| 
 | |
|    Should be near the bottom as it's a last-resort type of middleware.
 | |
| 
 | |
| #. :class:`~django.contrib.redirects.middleware.RedirectFallbackMiddleware`
 | |
| 
 | |
|    Should be near the bottom as it's a last-resort type of middleware.
 |