diff options
Diffstat (limited to 'docs')
28 files changed, 311 insertions, 1172 deletions
diff --git a/docs/howto/auth-remote-user.txt b/docs/howto/auth-remote-user.txt index 1680baa92b..5bfe210458 100644 --- a/docs/howto/auth-remote-user.txt +++ b/docs/howto/auth-remote-user.txt @@ -29,10 +29,10 @@ Configuration First, you must add the :class:`django.contrib.auth.middleware.RemoteUserMiddleware` to the -:setting:`MIDDLEWARE_CLASSES` setting **after** the +:setting:`MIDDLEWARE` setting **after** the :class:`django.contrib.auth.middleware.AuthenticationMiddleware`:: - MIDDLEWARE_CLASSES = [ + MIDDLEWARE = [ '...', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.RemoteUserMiddleware', diff --git a/docs/howto/error-reporting.txt b/docs/howto/error-reporting.txt index d07404a1e9..7a51338539 100644 --- a/docs/howto/error-reporting.txt +++ b/docs/howto/error-reporting.txt @@ -57,7 +57,7 @@ not found" errors). Django sends emails about 404 errors when: * :setting:`DEBUG` is ``False``; -* Your :setting:`MIDDLEWARE_CLASSES` setting includes +* Your :setting:`MIDDLEWARE` setting includes :class:`django.middleware.common.BrokenLinkEmailsMiddleware`. If those conditions are met, Django will email the users listed in the @@ -78,7 +78,7 @@ behavior is from broken Web bots too. before other middleware that intercepts 404 errors, such as :class:`~django.middleware.locale.LocaleMiddleware` or :class:`~django.contrib.flatpages.middleware.FlatpageFallbackMiddleware`. - Put it towards the top of your :setting:`MIDDLEWARE_CLASSES` setting. + Put it towards the top of your :setting:`MIDDLEWARE` setting. You can tell Django to stop reporting particular 404s by tweaking the :setting:`IGNORABLE_404_URLS` setting. It should be a list of compiled diff --git a/docs/ref/applications.txt b/docs/ref/applications.txt index be761505fe..53d9bcd9b5 100644 --- a/docs/ref/applications.txt +++ b/docs/ref/applications.txt @@ -37,8 +37,8 @@ projects. Applications include some combination of models, views, templates, template tags, static files, URLs, middleware, etc. They're generally wired into projects with the :setting:`INSTALLED_APPS` setting and optionally with other -mechanisms such as URLconfs, the :setting:`MIDDLEWARE_CLASSES` setting, or -template inheritance. +mechanisms such as URLconfs, the :setting:`MIDDLEWARE` setting, or template +inheritance. It is important to understand that a Django application is just a set of code that interacts with various parts of the framework. There's no such thing as diff --git a/docs/ref/checks.txt b/docs/ref/checks.txt index e4af02c1a2..5057ef18b6 100644 --- a/docs/ref/checks.txt +++ b/docs/ref/checks.txt @@ -491,19 +491,19 @@ The following checks are run if you use the :option:`check --deploy` option: * **security.W001**: You do not have :class:`django.middleware.security.SecurityMiddleware` in your - :setting:`MIDDLEWARE_CLASSES` so the :setting:`SECURE_HSTS_SECONDS`, + :setting:`MIDDLEWARE`/:setting:`MIDDLEWARE_CLASSES` so the :setting:`SECURE_HSTS_SECONDS`, :setting:`SECURE_CONTENT_TYPE_NOSNIFF`, :setting:`SECURE_BROWSER_XSS_FILTER`, and :setting:`SECURE_SSL_REDIRECT` settings will have no effect. * **security.W002**: You do not have :class:`django.middleware.clickjacking.XFrameOptionsMiddleware` in your - :setting:`MIDDLEWARE_CLASSES`, so your pages will not be served with an + :setting:`MIDDLEWARE`/:setting:`MIDDLEWARE_CLASSES`, so your pages will not be served with an ``'x-frame-options'`` header. Unless there is a good reason for your site to be served in a frame, you should consider enabling this header to help prevent clickjacking attacks. * **security.W003**: You don't appear to be using Django's built-in cross-site request forgery protection via the middleware (:class:`django.middleware.csrf.CsrfViewMiddleware` is not in your - :setting:`MIDDLEWARE_CLASSES`). Enabling the middleware is the safest + :setting:`MIDDLEWARE`/:setting:`MIDDLEWARE_CLASSES`). Enabling the middleware is the safest approach to ensure you don't leave any holes. * **security.W004**: You have not set a value for the :setting:`SECURE_HSTS_SECONDS` setting. If your entire site is served only @@ -540,7 +540,7 @@ The following checks are run if you use the :option:`check --deploy` option: sessions. * **security.W011**: You have :class:`django.contrib.sessions.middleware.SessionMiddleware` in your - :setting:`MIDDLEWARE_CLASSES`, but you have not set + :setting:`MIDDLEWARE`/:setting:`MIDDLEWARE_CLASSES`, but you have not set :setting:`SESSION_COOKIE_SECURE` to ``True``. Using a secure-only session cookie makes it more difficult for network traffic sniffers to hijack user sessions. @@ -554,7 +554,7 @@ The following checks are run if you use the :option:`check --deploy` option: sessions. * **security.W014**: You have :class:`django.contrib.sessions.middleware.SessionMiddleware` in your - :setting:`MIDDLEWARE_CLASSES`, but you have not set + :setting:`MIDDLEWARE`/:setting:`MIDDLEWARE_CLASSES`, but you have not set :setting:`SESSION_COOKIE_HTTPONLY` to ``True``. Using an ``HttpOnly`` session cookie makes it more difficult for cross-site scripting attacks to hijack user sessions. @@ -571,7 +571,7 @@ The following checks are run if you use the :option:`check --deploy` option: deployment. * **security.W019**: You have :class:`django.middleware.clickjacking.XFrameOptionsMiddleware` in your - :setting:`MIDDLEWARE_CLASSES`, but :setting:`X_FRAME_OPTIONS` is not set to + :setting:`MIDDLEWARE`/:setting:`MIDDLEWARE_CLASSES`, but :setting:`X_FRAME_OPTIONS` is not set to ``'DENY'``. The default is ``'SAMEORIGIN'``, but unless there is a good reason for your site to serve other parts of itself in a frame, you should change it to ``'DENY'``. diff --git a/docs/ref/clickjacking.txt b/docs/ref/clickjacking.txt index abac81dcd8..2f72e18d2f 100644 --- a/docs/ref/clickjacking.txt +++ b/docs/ref/clickjacking.txt @@ -56,9 +56,9 @@ Setting ``X-Frame-Options`` for all responses To set the same ``X-Frame-Options`` value for all responses in your site, put ``'django.middleware.clickjacking.XFrameOptionsMiddleware'`` to -:setting:`MIDDLEWARE_CLASSES`:: +:setting:`MIDDLEWARE`:: - MIDDLEWARE_CLASSES = [ + MIDDLEWARE = [ ... 'django.middleware.clickjacking.XFrameOptionsMiddleware', ... diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt index eed7d4451c..66b116ad35 100644 --- a/docs/ref/contrib/admin/index.txt +++ b/docs/ref/contrib/admin/index.txt @@ -41,8 +41,8 @@ For reference, here are the requirements: defined in your :setting:`TEMPLATES` as well as :class:`django.contrib.auth.middleware.AuthenticationMiddleware` and :class:`django.contrib.messages.middleware.MessageMiddleware` to - :setting:`MIDDLEWARE_CLASSES`. (These are all active by default, so - you only need to do this if you've manually tweaked the settings.) + :setting:`MIDDLEWARE`. These are all active by default, so you only need to + do this if you've manually tweaked the settings. 4. Determine which of your application's models should be editable in the admin interface. diff --git a/docs/ref/contrib/flatpages.txt b/docs/ref/contrib/flatpages.txt index 3326a93ea8..580f864c34 100644 --- a/docs/ref/contrib/flatpages.txt +++ b/docs/ref/contrib/flatpages.txt @@ -53,7 +53,7 @@ Then either: or: 3. Add ``'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware'`` - to your :setting:`MIDDLEWARE_CLASSES` setting. + to your :setting:`MIDDLEWARE` setting. 4. Run the command :djadmin:`manage.py migrate <migrate>`. @@ -144,8 +144,7 @@ can do all of the work. methods. Only requests which are successfully routed to a view via normal URL resolution apply view middleware. -Note that the order of :setting:`MIDDLEWARE_CLASSES` matters. Generally, you -can put +Note that the order of :setting:`MIDDLEWARE` matters. Generally, you can put :class:`~django.contrib.flatpages.middleware.FlatpageFallbackMiddleware` at the end of the list. This means it will run first when processing the response, and ensures that any other response-processing middlewares see the real flatpage diff --git a/docs/ref/contrib/messages.txt b/docs/ref/contrib/messages.txt index d425899cd9..414cf21116 100644 --- a/docs/ref/contrib/messages.txt +++ b/docs/ref/contrib/messages.txt @@ -27,14 +27,14 @@ already contains all the settings required to enable message functionality: * ``'django.contrib.messages'`` is in :setting:`INSTALLED_APPS`. -* :setting:`MIDDLEWARE_CLASSES` contains +* :setting:`MIDDLEWARE` contains ``'django.contrib.sessions.middleware.SessionMiddleware'`` and ``'django.contrib.messages.middleware.MessageMiddleware'``. The default :ref:`storage backend <message-storage-backends>` relies on :doc:`sessions </topics/http/sessions>`. That's why ``SessionMiddleware`` must be enabled and appear before ``MessageMiddleware`` in - :setting:`MIDDLEWARE_CLASSES`. + :setting:`MIDDLEWARE`. * The ``'context_processors'`` option of the ``DjangoTemplates`` backend defined in your :setting:`TEMPLATES` setting contains @@ -42,8 +42,8 @@ already contains all the settings required to enable message functionality: If you don't want to use messages, you can remove ``'django.contrib.messages'`` from your :setting:`INSTALLED_APPS`, the -``MessageMiddleware`` line from :setting:`MIDDLEWARE_CLASSES`, and the -``messages`` context processor from :setting:`TEMPLATES`. +``MessageMiddleware`` line from :setting:`MIDDLEWARE`, and the ``messages`` +context processor from :setting:`TEMPLATES`. Configuring the message engine ============================== diff --git a/docs/ref/contrib/redirects.txt b/docs/ref/contrib/redirects.txt index 2aadf8a45c..8af48ba8b2 100644 --- a/docs/ref/contrib/redirects.txt +++ b/docs/ref/contrib/redirects.txt @@ -18,7 +18,7 @@ To install the redirects app, follow these steps: :ref:`is installed <enabling-the-sites-framework>`. 2. Add ``'django.contrib.redirects'`` to your :setting:`INSTALLED_APPS` setting. 3. Add ``'django.contrib.redirects.middleware.RedirectFallbackMiddleware'`` - to your :setting:`MIDDLEWARE_CLASSES` setting. + to your :setting:`MIDDLEWARE` setting. 4. Run the command :djadmin:`manage.py migrate <migrate>`. How it works @@ -49,9 +49,9 @@ given ``old_path`` with a site ID that corresponds to the The middleware only gets activated for 404s -- not for 500s or responses of any other status code. -Note that the order of :setting:`MIDDLEWARE_CLASSES` matters. Generally, you -can put :class:`~django.contrib.redirects.middleware.RedirectFallbackMiddleware` -at the end of the list, because it's a last resort. +Note that the order of :setting:`MIDDLEWARE` matters. Generally, you can put +:class:`~django.contrib.redirects.middleware.RedirectFallbackMiddleware` at the +end of the list, because it's a last resort. For more on middleware, read the :doc:`middleware docs </topics/http/middleware>`. diff --git a/docs/ref/contrib/sites.txt b/docs/ref/contrib/sites.txt index 2f312d04e0..ec2c1bf2b2 100644 --- a/docs/ref/contrib/sites.txt +++ b/docs/ref/contrib/sites.txt @@ -405,8 +405,8 @@ If you often use this pattern:: there is simple way to avoid repetitions. Add :class:`django.contrib.sites.middleware.CurrentSiteMiddleware` to -:setting:`MIDDLEWARE_CLASSES`. The middleware sets the ``site`` attribute on -every request object, so you can use ``request.site`` to get the current site. +:setting:`MIDDLEWARE`. The middleware sets the ``site`` attribute on every +request object, so you can use ``request.site`` to get the current site. How Django uses the sites framework =================================== diff --git a/docs/ref/csrf.txt b/docs/ref/csrf.txt index f59b45646d..277fd85720 100644 --- a/docs/ref/csrf.txt +++ b/docs/ref/csrf.txt @@ -27,10 +27,10 @@ How to use it To take advantage of CSRF protection in your views, follow these steps: -1. The CSRF middleware is activated by default in the - :setting:`MIDDLEWARE_CLASSES` setting. If you override that setting, remember - that ``'django.middleware.csrf.CsrfViewMiddleware'`` should come before any - view middleware that assume that CSRF attacks have been dealt with. +1. The CSRF middleware is activated by default in the :setting:`MIDDLEWARE` + setting. If you override that setting, remember that + ``'django.middleware.csrf.CsrfViewMiddleware'`` should come before any view + middleware that assume that CSRF attacks have been dealt with. If you disabled it, which is not recommended, you can use :func:`~django.views.decorators.csrf.csrf_protect` on particular views diff --git a/docs/ref/middleware.txt b/docs/ref/middleware.txt index 49062d3474..1e582d5724 100644 --- a/docs/ref/middleware.txt +++ b/docs/ref/middleware.txt @@ -77,6 +77,36 @@ issued by the middleware. * 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 + +.. versionadded:: 1.10 + +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 --------------- diff --git a/docs/ref/request-response.txt b/docs/ref/request-response.txt index 64bd5960cd..96f5300f8b 100644 --- a/docs/ref/request-response.txt +++ b/docs/ref/request-response.txt @@ -176,9 +176,9 @@ All attributes should be considered read-only, unless stated otherwise. An instance of :class:`~django.urls.ResolverMatch` representing the resolved URL. This attribute is only set after URL resolving took place, - which means it's available in all views but not in middleware methods - which are executed before URL resolving takes place (like - ``process_request()``, you can use ``process_view()`` instead). + which means it's available in all views but not in middleware which are + executed before URL resolving takes place (you can use it in + :meth:`process_view` though). Attributes set by application code ---------------------------------- @@ -210,7 +210,7 @@ Attributes set by middleware Some of the middleware included in Django's contrib apps set attributes on the request. If you don't see the attribute on a request, be sure the appropriate -middleware class is listed in :setting:`MIDDLEWARE_CLASSES`. +middleware class is listed in :setting:`MIDDLEWARE`. .. attribute:: HttpRequest.session @@ -257,7 +257,9 @@ Methods behind multiple proxies. One solution is to use middleware to rewrite the proxy headers, as in the following example:: - class MultipleProxyMiddleware(object): + from django.django.utils.deprecation import MiddlewareMixin + + class MultipleProxyMiddleware(MiddlewareMixin): FORWARDED_FOR_FIELDS = [ 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED_HOST', diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt index 838dde808a..a7801f715c 100644 --- a/docs/ref/settings.txt +++ b/docs/ref/settings.txt @@ -77,7 +77,7 @@ can be used as a subdomain wildcard: ``'.example.com'`` will match ``example.com``. A value of ``'*'`` will match anything; in this case you are responsible to provide your own validation of the ``Host`` header (perhaps in a middleware; if so this middleware must be listed first in -:setting:`MIDDLEWARE_CLASSES`). +:setting:`MIDDLEWARE`). Django also allows the `fully qualified domain name (FQDN)`_ of any entries. Some browsers include a trailing dot in the ``Host`` header which Django @@ -1844,6 +1844,17 @@ Example: ``"http://media.example.com/"`` :setting:`MEDIA_URL` and :setting:`STATIC_URL` must have different values. See :setting:`MEDIA_ROOT` for more details. +.. setting:: MIDDLEWARE + +``MIDDLEWARE`` +-------------- + +.. versionadded:: 1.10 + +Default:: ``None`` + +A list of middleware to use. See :doc:`/topics/http/middleware`. + .. setting:: MIDDLEWARE_CLASSES ``MIDDLEWARE_CLASSES`` @@ -1856,7 +1867,11 @@ Default:: 'django.middleware.csrf.CsrfViewMiddleware', ] -A list of middleware classes to use. See :doc:`/topics/http/middleware`. +A list of middleware classes to use. This was the default setting used in +Django 1.9 and earlier. Django 1.10 introduced a new style of middleware. If +you have an older project using this setting you should :ref:`update any +middleware you've written yourself <upgrading-middleware>` to the new style +and then use the :setting:`MIDDLEWARE` setting. .. setting:: MIGRATION_MODULES @@ -3312,6 +3327,7 @@ HTTP * :setting:`DISALLOWED_USER_AGENTS` * :setting:`FORCE_SCRIPT_NAME` * :setting:`INTERNAL_IPS` +* :setting:`MIDDLEWARE` * :setting:`MIDDLEWARE_CLASSES` * Security diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt index f95ff1017f..1b527277af 100644 --- a/docs/ref/utils.txt +++ b/docs/ref/utils.txt @@ -173,6 +173,10 @@ The functions defined in this module share the following properties: middleware functionality on a per-view basis. The middleware is created with no params passed. + It assumes middleware that's compatible with the old style of Django 1.9 + and earlier (having methods like ``process_request()``, + ``process_exception()``, and ``process_response()``). + .. function:: decorator_from_middleware_with_args(middleware_class) Like ``decorator_from_middleware``, but returns a function diff --git a/docs/releases/1.10.txt b/docs/releases/1.10.txt index b6ac9f5c89..13e5f44d5b 100644 --- a/docs/releases/1.10.txt +++ b/docs/releases/1.10.txt @@ -37,6 +37,17 @@ It also now includes trigram support, using the :lookup:`trigram_similar` lookup, and the :class:`~django.contrib.postgres.search.TrigramSimilarity` and :class:`~django.contrib.postgres.search.TrigramDistance` expressions. +New-style middleware +-------------------- + +:doc:`A new style of middleware is introduced </topics/http/middleware>` to +solve the lack of strict request/response layering of the old-style of +middleware described in `DEP 0005 +<https://github.com/django/deps/blob/master/final/0005-improved-middleware.rst>`_. +You'll need to :ref:`adapt old, custom middleware <upgrading-middleware>` and +switch from the ``MIDDLEWARE_CLASSES`` setting to the new :setting:`MIDDLEWARE` +setting to take advantage of the improvements. + Official support for Unicode usernames -------------------------------------- diff --git a/docs/releases/1.5.txt b/docs/releases/1.5.txt index 3ecdcca12e..21da0dca61 100644 --- a/docs/releases/1.5.txt +++ b/docs/releases/1.5.txt @@ -188,8 +188,7 @@ is an iterator. Since :class:`~django.http.StreamingHttpResponse` does not have a ``content`` attribute, middleware that needs access to the response content must test for -streaming responses and behave accordingly. See :ref:`response-middleware` for -more information. +streaming responses and behave accordingly. ``{% verbatim %}`` template tag ------------------------------- diff --git a/docs/topics/auth/default.txt b/docs/topics/auth/default.txt index 45526eb831..7e6794a97b 100644 --- a/docs/topics/auth/default.txt +++ b/docs/topics/auth/default.txt @@ -838,7 +838,7 @@ Session invalidation on password change ``SessionAuthenticationMiddleware`` is enabled. In older versions, this protection only applies if ``django.contrib.auth.middleware.SessionAuthenticationMiddleware`` - is enabled in :setting:`MIDDLEWARE_CLASSES`. + is enabled in :setting:`MIDDLEWARE`. If your :setting:`AUTH_USER_MODEL` inherits from :class:`~django.contrib.auth.models.AbstractBaseUser` or implements its own diff --git a/docs/topics/auth/index.txt b/docs/topics/auth/index.txt index b57c2e7436..3224af74c7 100644 --- a/docs/topics/auth/index.txt +++ b/docs/topics/auth/index.txt @@ -60,7 +60,7 @@ startproject <startproject>`, these consist of two items listed in your </ref/contrib/contenttypes>`, which allows permissions to be associated with models you create. -and these items in your :setting:`MIDDLEWARE_CLASSES` setting: +and these items in your :setting:`MIDDLEWARE` setting: 1. :class:`~django.contrib.sessions.middleware.SessionMiddleware` manages :doc:`sessions </topics/http/sessions>` across requests. diff --git a/docs/topics/cache.txt b/docs/topics/cache.txt index ad353e65e0..d955b853b4 100644 --- a/docs/topics/cache.txt +++ b/docs/topics/cache.txt @@ -447,9 +447,9 @@ Once the cache is set up, the simplest way to use caching is to cache your entire site. You'll need to add ``'django.middleware.cache.UpdateCacheMiddleware'`` and ``'django.middleware.cache.FetchFromCacheMiddleware'`` to your -:setting:`MIDDLEWARE_CLASSES` setting, as in this example:: +:setting:`MIDDLEWARE` setting, as in this example:: - MIDDLEWARE_CLASSES = [ + MIDDLEWARE = [ 'django.middleware.cache.UpdateCacheMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.cache.FetchFromCacheMiddleware', @@ -459,7 +459,7 @@ entire site. You'll need to add No, that's not a typo: the "update" middleware must be first in the list, and the "fetch" middleware must be last. The details are a bit obscure, but - see `Order of MIDDLEWARE_CLASSES`_ below if you'd like the full story. + see `Order of MIDDLEWARE`_ below if you'd like the full story. Then, add the following required settings to your Django settings file: @@ -1217,11 +1217,11 @@ Example:: def myview(request): ... -Order of ``MIDDLEWARE_CLASSES`` -=============================== +Order of ``MIDDLEWARE`` +======================= If you use caching middleware, it's important to put each half in the right -place within the :setting:`MIDDLEWARE_CLASSES` setting. That's because the cache +place within the :setting:`MIDDLEWARE` setting. That's because the cache middleware needs to know which headers by which to vary the cache storage. Middleware always adds something to the ``Vary`` response header when it can. diff --git a/docs/topics/http/_images/middleware.graffle b/docs/topics/http/_images/middleware.graffle deleted file mode 100644 index cdefd4b810..0000000000 --- a/docs/topics/http/_images/middleware.graffle +++ /dev/null @@ -1,957 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>ActiveLayerIndex</key> - <integer>0</integer> - <key>ApplicationVersion</key> - <array> - <string>com.omnigroup.OmniGrafflePro</string> - <string>139.16.0.171715</string> - </array> - <key>AutoAdjust</key> - <true/> - <key>BackgroundGraphic</key> - <dict> - <key>Bounds</key> - <string>{{0, 0}, {559.28997802734375, 782.8900146484375}}</string> - <key>Class</key> - <string>SolidGraphic</string> - <key>ID</key> - <integer>2</integer> - <key>Style</key> - <dict> - <key>shadow</key> - <dict> - <key>Draws</key> - <string>NO</string> - </dict> - <key>stroke</key> - <dict> - <key>Draws</key> - <string>NO</string> - </dict> - </dict> - </dict> - <key>BaseZoom</key> - <integer>0</integer> - <key>CanvasOrigin</key> - <string>{0, 0}</string> - <key>ColumnAlign</key> - <integer>1</integer> - <key>ColumnSpacing</key> - <real>36</real> - <key>CreationDate</key> - <string>2012-12-09 18:55:12 +0000</string> - <key>Creator</key> - <string>Aymeric Augustin</string> - <key>DisplayScale</key> - <string>1.000 cm = 1.000 cm</string> - <key>GraphDocumentVersion</key> - <integer>8</integer> - <key>GraphicsList</key> - <array> - <dict> - <key>Bounds</key> - <string>{{144, 405}, {369, 27}}</string> - <key>Class</key> - <string>ShapedGraphic</string> - <key>ID</key> - <integer>33</integer> - <key>Shape</key> - <string>Bezier</string> - <key>ShapeData</key> - <dict> - <key>UnitPoints</key> - <array> - <string>{-0.5, -0.5}</string> - <string>{-0.5, -0.5}</string> - <string>{0.47959183673469341, -0.5}</string> - <string>{0.47959183673469408, -0.5}</string> - <string>{0.47959183673469341, -0.5}</string> - <string>{0.5, 0}</string> - <string>{0.5, 0}</string> - <string>{0.5, 0}</string> - <string>{0.47959183673469408, 0.5}</string> - <string>{0.47959183673469408, 0.5}</string> - <string>{0.47959183673469408, 0.5}</string> - <string>{-0.5, 0.5}</string> - <string>{-0.5, 0.5}</string> - <string>{-0.5, 0.5}</string> - <string>{-0.47560975609756084, 0}</string> - <string>{-0.47560975609756084, 0}</string> - <string>{-0.47560975609756084, 0}</string> - <string>{-0.5, -0.5}</string> - </array> - </dict> - <key>Text</key> - <dict> - <key>Text</key> - <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 view function}</string> - </dict> - </dict> - <dict> - <key>Bounds</key> - <string>{{229.5, 238.5}, {297, 36}}</string> - <key>Class</key> - <string>ShapedGraphic</string> - <key>ID</key> - <integer>31</integer> - <key>Rotation</key> - <real>270</real> - <key>Shape</key> - <string>AdjustableArrow</string> - <key>ShapeData</key> - <dict> - <key>width</key> - <real>27</real> - </dict> - <key>Style</key> - <dict> - <key>fill</key> - <dict> - <key>Color</key> - <dict> - <key>a</key> - <string>0.8</string> - <key>b</key> - <string>1</string> - <key>g</key> - <string>1</string> - <key>r</key> - <string>1</string> - </dict> - <key>MiddleFraction</key> - <real>0.70634919404983521</real> - </dict> - <key>shadow</key> - <dict> - <key>Color</key> - <dict> - <key>a</key> - <string>0.4</string> - <key>b</key> - <string>0</string> - <key>g</key> - <string>0</string> - <key>r</key> - <string>0</string> - </dict> - <key>Draws</key> - <string>NO</string> - <key>Fuzziness</key> - <real>0.0</real> - <key>ShadowVector</key> - <string>{0, 2}</string> - </dict> - <key>stroke</key> - <dict> - <key>Color</key> - <dict> - <key>b</key> - <string>0</string> - <key>g</key> - <string>0</string> - <key>r</key> - <string>1</string> - </dict> - <key>Pattern</key> - <integer>1</integer> - </dict> - </dict> - <key>Text</key> - <dict> - <key>Text</key> - <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fmodern\fcharset0 Courier;} -{\colortbl;\red255\green255\blue255;\red255\green0\blue0;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 process_exception}</string> - </dict> - <key>TextRelativeArea</key> - <string>{{0.125, 0.25}, {0.75, 0.5}}</string> - <key>isConnectedShape</key> - <true/> - </dict> - <dict> - <key>Bounds</key> - <string>{{328.5, 229.5}, {315, 36}}</string> - <key>Class</key> - <string>ShapedGraphic</string> - <key>ID</key> - <integer>30</integer> - <key>Rotation</key> - <real>270</real> - <key>Shape</key> - <string>AdjustableArrow</string> - <key>ShapeData</key> - <dict> - <key>width</key> - <real>27</real> - </dict> - <key>Style</key> - <dict> - <key>fill</key> - <dict> - <key>Color</key> - <dict> - <key>a</key> - <string>0.8</string> - <key>b</key> - <string>1</string> - <key>g</key> - <string>1</string> - <key>r</key> - <string>1</string> - </dict> - <key>MiddleFraction</key> - <real>0.70634919404983521</real> - </dict> - <key>shadow</key> - <dict> - <key>Color</key> - <dict> - <key>a</key> - <string>0.4</string> - <key>b</key> - <string>0</string> - <key>g</key> - <string>0</string> - <key>r</key> - <string>0</string> - </dict> - <key>Draws</key> - <string>NO</string> - <key>Fuzziness</key> - <real>0.0</real> - <key>ShadowVector</key> - <string>{0, 2}</string> - </dict> - <key>stroke</key> - <dict> - <key>Color</key> - <dict> - <key>b</key> - <string>0</string> - <key>g</key> - <string>0.501961</string> - <key>r</key> - <string>0</string> - </dict> - </dict> - </dict> - <key>Text</key> - <dict> - <key>Text</key> - <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fmodern\fcharset0 Courier;} -{\colortbl;\red255\green255\blue255;\red0\green128\blue0;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 process_response}</string> - </dict> - <key>TextRelativeArea</key> - <string>{{0.125, 0.25}, {0.75, 0.5}}</string> - <key>isConnectedShape</key> - <true/> - </dict> - <dict> - <key>Bounds</key> - <string>{{283.5, 238.5}, {297, 36}}</string> - <key>Class</key> - <string>ShapedGraphic</string> - <key>ID</key> - <integer>29</integer> - <key>Rotation</key> - <real>270</real> - <key>Shape</key> - <string>AdjustableArrow</string> - <key>ShapeData</key> - <dict> - <key>width</key> - <real>27</real> - </dict> - <key>Style</key> - <dict> - <key>fill</key> - <dict> - <key>Color</key> - <dict> - <key>a</key> - <string>0.8</string> - <key>b</key> - <string>1</string> - <key>g</key> - <string>1</string> - <key>r</key> - <string>1</string> - </dict> - <key>MiddleFraction</key> - <real>0.70634919404983521</real> - </dict> - <key>shadow</key> - <dict> - <key>Color</key> - <dict> - <key>a</key> - <string>0.4</string> - <key>b</key> - <string>0</string> - <key>g</key> - <string>0</string> - <key>r</key> - <string>0</string> - </dict> - <key>Draws</key> - <string>NO</string> - <key>Fuzziness</key> - <real>0.0</real> - <key>ShadowVector</key> - <string>{0, 2}</string> - </dict> - <key>stroke</key> - <dict> - <key>Color</key> - <dict> - <key>b</key> - <string>0</string> - <key>g</key> - <string>0.501961</string> - <key>r</key> - <string>0</string> - </dict> - <key>Pattern</key> - <integer>1</integer> - </dict> - </dict> - <key>Text</key> - <dict> - <key>Text</key> - <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fmodern\fcharset0 Courier;} -{\colortbl;\red255\green255\blue255;\red0\green128\blue0;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 process_template_response}</string> - </dict> - <key>TextRelativeArea</key> - <string>{{0.125, 0.25}, {0.75, 0.5}}</string> - <key>isConnectedShape</key> - <true/> - </dict> - <dict> - <key>Bounds</key> - <string>{{27, 243}, {288, 36}}</string> - <key>Class</key> - <string>ShapedGraphic</string> - <key>ID</key> - <integer>28</integer> - <key>Rotation</key> - <real>90</real> - <key>Shape</key> - <string>AdjustableArrow</string> - <key>ShapeData</key> - <dict> - <key>width</key> - <real>27</real> - </dict> - <key>Style</key> - <dict> - <key>fill</key> - <dict> - <key>Color</key> - <dict> - <key>a</key> - <string>0.8</string> - <key>b</key> - <string>1</string> - <key>g</key> - <string>1</string> - <key>r</key> - <string>1</string> - </dict> - <key>MiddleFraction</key> - <real>0.70634919404983521</real> - </dict> - <key>shadow</key> - <dict> - <key>Color</key> - <dict> - <key>a</key> - <string>0.4</string> - <key>b</key> - <string>0</string> - <key>g</key> - <string>0</string> - <key>r</key> - <string>0</string> - </dict> - <key>Draws</key> - <string>NO</string> - <key>Fuzziness</key> - <real>0.0</real> - <key>ShadowVector</key> - <string>{0, 2}</string> - </dict> - <key>stroke</key> - <dict> - <key>Color</key> - <dict> - <key>b</key> - <string>0</string> - <key>g</key> - <string>0.501961</string> - <key>r</key> - <string>0</string> - </dict> - </dict> - </dict> - <key>Text</key> - <dict> - <key>Text</key> - <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fmodern\fcharset0 Courier;} -{\colortbl;\red255\green255\blue255;\red0\green128\blue0;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 process_view}</string> - </dict> - <key>TextRelativeArea</key> - <string>{{0.125, 0.25}, {0.75, 0.5}}</string> - <key>isConnectedShape</key> - <true/> - </dict> - <dict> - <key>Bounds</key> - <string>{{-40.500000000767386, 220.49999999804004}, {297, 36}}</string> - <key>Class</key> - <string>ShapedGraphic</string> - <key>ID</key> - <integer>27</integer> - <key>Rotation</key> - <real>90</real> - <key>Shape</key> - <string>AdjustableArrow</string> - <key>ShapeData</key> - <dict> - <key>width</key> - <real>27</real> - </dict> - <key>Style</key> - <dict> - <key>fill</key> - <dict> - <key>Color</key> - <dict> - <key>a</key> - <string>0.8</string> - <key>b</key> - <string>1</string> - <key>g</key> - <string>1</string> - <key>r</key> - <string>1</string> - </dict> - <key>MiddleFraction</key> - <real>0.70634919404983521</real> - </dict> - <key>shadow</key> - <dict> - <key>Color</key> - <dict> - <key>a</key> - <string>0.4</string> - <key>b</key> - <string>0</string> - <key>g</key> - <string>0</string> - <key>r</key> - <string>0</string> - </dict> - <key>Draws</key> - <string>NO</string> - <key>Fuzziness</key> - <real>0.0</real> - <key>ShadowVector</key> - <string>{0, 2}</string> - </dict> - <key>stroke</key> - <dict> - <key>Color</key> - <dict> - <key>b</key> - <string>0</string> - <key>g</key> - <string>0.501961</string> - <key>r</key> - <string>0</string> - </dict> - </dict> - </dict> - <key>Text</key> - <dict> - <key>Text</key> - <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fmodern\fcharset0 Courier;} -{\colortbl;\red255\green255\blue255;\red0\green128\blue0;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf2 process_request}</string> - </dict> - <key>TextRelativeArea</key> - <string>{{0.125, 0.25}, {0.75, 0.5}}</string> - <key>isConnectedShape</key> - <true/> - </dict> - <dict> - <key>Bounds</key> - <string>{{360, 63}, {144, 27}}</string> - <key>Class</key> - <string>ShapedGraphic</string> - <key>ID</key> - <integer>12</integer> - <key>Magnets</key> - <array> - <string>{0, 1}</string> - <string>{0, -1}</string> - <string>{1, 0}</string> - <string>{-1, 0}</string> - </array> - <key>Shape</key> - <string>Rectangle</string> - <key>Text</key> - <dict> - <key>Text</key> - <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fmodern\fcharset0 Courier;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 HttpResponse}</string> - </dict> - </dict> - <dict> - <key>Bounds</key> - <string>{{72, 63}, {144, 27}}</string> - <key>Class</key> - <string>ShapedGraphic</string> - <key>ID</key> - <integer>11</integer> - <key>Magnets</key> - <array> - <string>{0, 1}</string> - <string>{0, -1}</string> - <string>{1, 0}</string> - <string>{-1, 0}</string> - </array> - <key>Shape</key> - <string>Rectangle</string> - <key>Text</key> - <dict> - <key>Text</key> - <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fmodern\fcharset0 Courier;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 HttpRequest}</string> - </dict> - </dict> - <dict> - <key>Bounds</key> - <string>{{72, 324}, {432, 27}}</string> - <key>Class</key> - <string>ShapedGraphic</string> - <key>ID</key> - <integer>10</integer> - <key>Magnets</key> - <array> - <string>{0, 1}</string> - <string>{0, -1}</string> - <string>{1, 0}</string> - <string>{-1, 0}</string> - </array> - <key>Shape</key> - <string>Rectangle</string> - <key>Style</key> - <dict> - <key>fill</key> - <dict> - <key>FillType</key> - <integer>2</integer> - <key>GradientAngle</key> - <real>90</real> - <key>GradientColor</key> - <dict> - <key>w</key> - <string>0.666667</string> - </dict> - </dict> - <key>stroke</key> - <dict> - <key>CornerRadius</key> - <real>5</real> - </dict> - </dict> - <key>Text</key> - <dict> - <key>Text</key> - <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fmodern\fcharset0 Courier;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 MessageMiddleware}</string> - </dict> - </dict> - <dict> - <key>Bounds</key> - <string>{{72, 279}, {432, 27}}</string> - <key>Class</key> - <string>ShapedGraphic</string> - <key>ID</key> - <integer>9</integer> - <key>Magnets</key> - <array> - <string>{0, 1}</string> - <string>{0, -1}</string> - <string>{1, 0}</string> - <string>{-1, 0}</string> - </array> - <key>Shape</key> - <string>Rectangle</string> - <key>Style</key> - <dict> - <key>fill</key> - <dict> - <key>FillType</key> - <integer>2</integer> - <key>GradientAngle</key> - <real>90</real> - <key>GradientColor</key> - <dict> - <key>w</key> - <string>0.666667</string> - </dict> - </dict> - <key>stroke</key> - <dict> - <key>CornerRadius</key> - <real>5</real> - </dict> - </dict> - <key>Text</key> - <dict> - <key>Text</key> - <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fmodern\fcharset0 Courier;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 AuthenticationMiddleware}</string> - </dict> - </dict> - <dict> - <key>Bounds</key> - <string>{{72, 234}, {432, 27}}</string> - <key>Class</key> - <string>ShapedGraphic</string> - <key>ID</key> - <integer>8</integer> - <key>Magnets</key> - <array> - <string>{0, 1}</string> - <string>{0, -1}</string> - <string>{1, 0}</string> - <string>{-1, 0}</string> - </array> - <key>Shape</key> - <string>Rectangle</string> - <key>Style</key> - <dict> - <key>fill</key> - <dict> - <key>FillType</key> - <integer>2</integer> - <key>GradientAngle</key> - <real>90</real> - <key>GradientColor</key> - <dict> - <key>w</key> - <string>0.666667</string> - </dict> - </dict> - <key>stroke</key> - <dict> - <key>CornerRadius</key> - <real>5</real> - </dict> - </dict> - <key>Text</key> - <dict> - <key>Text</key> - <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fmodern\fcharset0 Courier;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 CsrfViewMiddleware}</string> - </dict> - </dict> - <dict> - <key>Bounds</key> - <string>{{72, 189}, {432, 27}}</string> - <key>Class</key> - <string>ShapedGraphic</string> - <key>ID</key> - <integer>7</integer> - <key>Magnets</key> - <array> - <string>{0, 1}</string> - <string>{0, -1}</string> - <string>{1, 0}</string> - <string>{-1, 0}</string> - </array> - <key>Shape</key> - <string>Rectangle</string> - <key>Style</key> - <dict> - <key>fill</key> - <dict> - <key>FillType</key> - <integer>2</integer> - <key>GradientAngle</key> - <real>90</real> - <key>GradientColor</key> - <dict> - <key>w</key> - <string>0.666667</string> - </dict> - </dict> - <key>stroke</key> - <dict> - <key>CornerRadius</key> - <real>5</real> - </dict> - </dict> - <key>Text</key> - <dict> - <key>Text</key> - <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fmodern\fcharset0 Courier;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 SessionMiddleware}</string> - </dict> - </dict> - <dict> - <key>Bounds</key> - <string>{{72, 144}, {432, 27}}</string> - <key>Class</key> - <string>ShapedGraphic</string> - <key>ID</key> - <integer>6</integer> - <key>Magnets</key> - <array> - <string>{0, 1}</string> - <string>{0, -1}</string> - <string>{1, 0}</string> - <string>{-1, 0}</string> - </array> - <key>Shape</key> - <string>Rectangle</string> - <key>Style</key> - <dict> - <key>fill</key> - <dict> - <key>FillType</key> - <integer>2</integer> - <key>GradientAngle</key> - <real>90</real> - <key>GradientColor</key> - <dict> - <key>w</key> - <string>0.666667</string> - </dict> - </dict> - <key>stroke</key> - <dict> - <key>CornerRadius</key> - <real>5</real> - </dict> - </dict> - <key>Text</key> - <dict> - <key>Text</key> - <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 -\cocoascreenfonts1{\fonttbl\f0\fmodern\fcharset0 Courier;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs24 \cf0 CommonMiddleware}</string> - </dict> - </dict> - </array> - <key>GridInfo</key> - <dict> - <key>ShowsGrid</key> - <string>YES</string> - <key>SnapsToGrid</key> - <string>YES</string> - </dict> - <key>GuidesLocked</key> - <string>NO</string> - <key>GuidesVisible</key> - <string>YES</string> - <key>HPages</key> - <integer>1</integer> - <key>ImageCounter</key> - <integer>1</integer> - <key>KeepToScale</key> - <false/> - <key>Layers</key> - <array> - <dict> - <key>Lock</key> - <string>NO</string> - <key>Name</key> - <string>Calque 1</string> - <key>Print</key> - <string>YES</string> - <key>View</key> - <string>YES</string> - </dict> - </array> - <key>LayoutInfo</key> - <dict> - <key>Animate</key> - <string>NO</string> - <key>circoMinDist</key> - <real>18</real> - <key>circoSeparation</key> - <real>0.0</real> - <key>layoutEngine</key> - <string>dot</string> - <key>neatoSeparation</key> - <real>0.0</real> - <key>twopiSeparation</key> - <real>0.0</real> - </dict> - <key>LinksVisible</key> - <string>NO</string> - <key>MagnetsVisible</key> - <string>NO</string> - <key>MasterSheets</key> - <array/> - <key>ModificationDate</key> - <string>2012-12-09 19:48:54 +0000</string> - <key>Modifier</key> - <string>Aymeric Augustin</string> - <key>NotesVisible</key> - <string>NO</string> - <key>Orientation</key> - <integer>2</integer> - <key>OriginVisible</key> - <string>NO</string> - <key>PageBreaks</key> - <string>YES</string> - <key>PrintInfo</key> - <dict> - <key>NSBottomMargin</key> - <array> - <string>float</string> - <string>41</string> - </array> - <key>NSHorizonalPagination</key> - <array> - <string>coded</string> - <string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string> - </array> - <key>NSLeftMargin</key> - <array> - <string>float</string> - <string>18</string> - </array> - <key>NSPaperSize</key> - <array> - <string>size</string> - <string>{595.28997802734375, 841.8900146484375}</string> - </array> - <key>NSPrintReverseOrientation</key> - <array> - <string>int</string> - <string>0</string> - </array> - <key>NSRightMargin</key> - <array> - <string>float</string> - <string>18</string> - </array> - <key>NSTopMargin</key> - <array> - <string>float</string> - <string>18</string> - </array> - </dict> - <key>PrintOnePage</key> - <false/> - <key>ReadOnly</key> - <string>NO</string> - <key>RowAlign</key> - <integer>1</integer> - <key>RowSpacing</key> - <real>36</real> - <key>SheetTitle</key> - <string>Canevas 1</string> - <key>SmartAlignmentGuidesActive</key> - <string>YES</string> - <key>SmartDistanceGuidesActive</key> - <string>YES</string> - <key>UniqueID</key> - <integer>1</integer> - <key>UseEntirePage</key> - <false/> - <key>VPages</key> - <integer>1</integer> - <key>WindowInfo</key> - <dict> - <key>CurrentSheet</key> - <integer>0</integer> - <key>ExpandedCanvases</key> - <array/> - <key>Frame</key> - <string>{{248, 4}, {694, 874}}</string> - <key>ListView</key> - <true/> - <key>OutlineWidth</key> - <integer>142</integer> - <key>RightSidebar</key> - <false/> - <key>ShowRuler</key> - <true/> - <key>Sidebar</key> - <true/> - <key>SidebarWidth</key> - <integer>120</integer> - <key>VisibleRegion</key> - <string>{{0, 0}, {559, 735}}</string> - <key>Zoom</key> - <real>1</real> - <key>ZoomValues</key> - <array> - <array> - <string>Canevas 1</string> - <real>1</real> - <real>1</real> - </array> - </array> - </dict> -</dict> -</plist> diff --git a/docs/topics/http/_images/middleware.svg b/docs/topics/http/_images/middleware.svg deleted file mode 100644 index 4da8d22da8..0000000000 --- a/docs/topics/http/_images/middleware.svg +++ /dev/null @@ -1,3 +0,0 @@ -<?xml version="1.0"?> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="52 47 481 409" width="481pt" height="409pt"><metadata xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:date>2012-12-09 19:48Z</dc:date><!-- Produced by OmniGraffle Professional 5.4.2 --></metadata><defs><filter id="Shadow" filterUnits="userSpaceOnUse"><feGaussianBlur in="SourceAlpha" result="blur" stdDeviation="3.488"/><feOffset in="blur" result="offset" dx="0" dy="4"/><feFlood flood-color="black" flood-opacity=".75" result="flood"/><feComposite in="flood" in2="offset" operator="in"/></filter><linearGradient x1="0" x2="1" id="Gradient" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#aaa"/></linearGradient><linearGradient id="Obj_Gradient" xl:href="#Gradient" gradientTransform="translate(288 144) rotate(90) scale(27)"/><font-face font-family="Courier" font-size="12" units-per-em="1000" underline-position="-178.22266" underline-thickness="57.617188" slope="0" x-height="462.40234" cap-height="594.72656" ascent="753.90625" descent="-246.09375" font-weight="500"><font-face-src><font-face-name name="Courier"/></font-face-src></font-face><linearGradient id="Obj_Gradient_2" xl:href="#Gradient" gradientTransform="translate(288 189) rotate(90) scale(27)"/><linearGradient id="Obj_Gradient_3" xl:href="#Gradient" gradientTransform="translate(288 234) rotate(90) scale(27)"/><linearGradient id="Obj_Gradient_4" xl:href="#Gradient" gradientTransform="translate(288 279) rotate(90) scale(27)"/><linearGradient id="Obj_Gradient_5" xl:href="#Gradient" gradientTransform="translate(288 324) rotate(90) scale(27)"/><font-face font-family="Helvetica" font-size="12" units-per-em="1000" underline-position="-75.683594" underline-thickness="49.316406" slope="0" x-height="522.94922" cap-height="717.28516" ascent="770.01953" descent="-229.98047" font-weight="500"><font-face-src><font-face-name name="Helvetica"/></font-face-src></font-face></defs><g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1"><title>Canevas 1</title><rect fill="white" width="559.28998" height="782.89"/><g><title>Calque 1</title><g><use xl:href="#id6_Graphic" filter="url(#Shadow)"/><use xl:href="#id7_Graphic" filter="url(#Shadow)"/><use xl:href="#id8_Graphic" filter="url(#Shadow)"/><use xl:href="#id9_Graphic" filter="url(#Shadow)"/><use xl:href="#id10_Graphic" filter="url(#Shadow)"/><use xl:href="#id11_Graphic" filter="url(#Shadow)"/><use xl:href="#id12_Graphic" filter="url(#Shadow)"/><use xl:href="#id33_Graphic" filter="url(#Shadow)"/></g><g id="id6_Graphic"><path d="M 77 144 L 499 144 C 501.76142 144 504 146.23858 504 149 L 504 166 C 504 168.76142 501.76142 171 499 171 L 77 171 C 74.238576 171 72 168.76142 72 166 C 72 166 72 166 72 166 L 72 149 C 72 146.23858 74.238576 144 77 144 C 77 144 77 144 77 144 Z" fill="url(#Obj_Gradient)"/><path d="M 77 144 L 499 144 C 501.76142 144 504 146.23858 504 149 L 504 166 C 504 168.76142 501.76142 171 499 171 L 77 171 C 74.238576 171 72 168.76142 72 166 C 72 166 72 166 72 166 L 72 149 C 72 146.23858 74.238576 144 77 144 C 77 144 77 144 77 144 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(77 150.5)" fill="black"><tspan font-family="Courier" font-size="12" font-weight="500" fill="black" x="153.390625" y="11" textLength="115.21875">CommonMiddleware</tspan></text></g><g id="id7_Graphic"><path d="M 77 189 L 499 189 C 501.76142 189 504 191.23858 504 194 L 504 211 C 504 213.76142 501.76142 216 499 216 L 77 216 C 74.238576 216 72 213.76142 72 211 C 72 211 72 211 72 211 L 72 194 C 72 191.23858 74.238576 189 77 189 C 77 189 77 189 77 189 Z" fill="url(#Obj_Gradient_2)"/><path d="M 77 189 L 499 189 C 501.76142 189 504 191.23858 504 194 L 504 211 C 504 213.76142 501.76142 216 499 216 L 77 216 C 74.238576 216 72 213.76142 72 211 C 72 211 72 211 72 211 L 72 194 C 72 191.23858 74.238576 189 77 189 C 77 189 77 189 77 189 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(77 195.5)" fill="black"><tspan font-family="Courier" font-size="12" font-weight="500" x="149.79004" y="11" textLength="122.41992">SessionMiddleware</tspan></text></g><g id="id8_Graphic"><path d="M 77 234 L 499 234 C 501.76142 234 504 236.23858 504 239 L 504 256 C 504 258.76142 501.76142 261 499 261 L 77 261 C 74.238576 261 72 258.76142 72 256 C 72 256 72 256 72 256 L 72 239 C 72 236.23858 74.238576 234 77 234 C 77 234 77 234 77 234 Z" fill="url(#Obj_Gradient_3)"/><path d="M 77 234 L 499 234 C 501.76142 234 504 236.23858 504 239 L 504 256 C 504 258.76142 501.76142 261 499 261 L 77 261 C 74.238576 261 72 258.76142 72 256 C 72 256 72 256 72 256 L 72 239 C 72 236.23858 74.238576 234 77 234 C 77 234 77 234 77 234 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(77 240.5)" fill="black"><tspan font-family="Courier" font-size="12" font-weight="500" x="146.18945" y="11" textLength="129.62109">CsrfViewMiddleware</tspan></text></g><g id="id9_Graphic"><path d="M 77 279 L 499 279 C 501.76142 279 504 281.23858 504 284 L 504 301 C 504 303.76142 501.76142 306 499 306 L 77 306 C 74.238576 306 72 303.76142 72 301 C 72 301 72 301 72 301 L 72 284 C 72 281.23858 74.238576 279 77 279 C 77 279 77 279 77 279 Z" fill="url(#Obj_Gradient_4)"/><path d="M 77 279 L 499 279 C 501.76142 279 504 281.23858 504 284 L 504 301 C 504 303.76142 501.76142 306 499 306 L 77 306 C 74.238576 306 72 303.76142 72 301 C 72 301 72 301 72 301 L 72 284 C 72 281.23858 74.238576 279 77 279 C 77 279 77 279 77 279 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(77 285.5)" fill="black"><tspan font-family="Courier" font-size="12" font-weight="500" x="124.58594" y="11" textLength="172.82812">AuthenticationMiddleware</tspan></text></g><g id="id10_Graphic"><path d="M 77 324 L 499 324 C 501.76142 324 504 326.23858 504 329 L 504 346 C 504 348.76142 501.76142 351 499 351 L 77 351 C 74.238576 351 72 348.76142 72 346 C 72 346 72 346 72 346 L 72 329 C 72 326.23858 74.238576 324 77 324 C 77 324 77 324 77 324 Z" fill="url(#Obj_Gradient_5)"/><path d="M 77 324 L 499 324 C 501.76142 324 504 326.23858 504 329 L 504 346 C 504 348.76142 501.76142 351 499 351 L 77 351 C 74.238576 351 72 348.76142 72 346 C 72 346 72 346 72 346 L 72 329 C 72 326.23858 74.238576 324 77 324 C 77 324 77 324 77 324 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(77 330.5)" fill="black"><tspan font-family="Courier" font-size="12" font-weight="500" x="149.79004" y="11" textLength="122.41992">MessageMiddleware</tspan></text></g><g id="id11_Graphic"><rect x="72" y="63" width="144" height="27" fill="white"/><rect x="72" y="63" width="144" height="27" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(77 69.5)" fill="black"><tspan font-family="Courier" font-size="12" font-weight="500" x="27.393555" y="11" textLength="79.21289">HttpRequest</tspan></text></g><g id="id12_Graphic"><rect x="360" y="63" width="144" height="27" fill="white"/><rect x="360" y="63" width="144" height="27" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(365 69.5)" fill="black"><tspan font-family="Courier" font-size="12" font-weight="500" x="23.792969" y="11" textLength="86.41406">HttpResponse</tspan></text></g><path d="M 99 90 L 117 90 L 117 360 L 126 360 L 108 387 L 90 360 L 99 360 Z" fill="white" fill-opacity=".8"/><path d="M 99 90 L 117 90 L 117 360 L 126 360 L 108 387 L 90 360 L 99 360 Z" stroke="green" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(115 132.125) rotate(90)" fill="green"><tspan font-family="Courier" font-size="12" font-weight="500" fill="green" x="52.36621" y="11" textLength="108.01758">process_request</tspan></text><path d="M 162 117 L 180 117 L 180 378 L 189 378 L 171 405 L 153 378 L 162 378 Z" fill="white" fill-opacity=".8"/><path d="M 162 117 L 180 117 L 180 378 L 189 378 L 171 405 L 153 378 L 162 378 Z" stroke="green" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(178 158) rotate(90)" fill="green"><tspan font-family="Courier" font-size="12" font-weight="500" fill="green" x="59.79297" y="11" textLength="86.41406">process_view</tspan></text><path d="M 441 405 L 423 405 L 423 135 L 414 135 L 432 108 L 450 135 L 441 135 Z" fill="white" fill-opacity=".8"/><path d="M 441 405 L 423 405 L 423 135 L 414 135 L 432 108 L 450 135 L 441 135 Z" stroke="green" stroke-linecap="round" stroke-linejoin="round" stroke-width="1" stroke-dasharray="4,4"/><text transform="translate(425 362.875) rotate(-90)" fill="green"><tspan font-family="Courier" font-size="12" font-weight="500" fill="green" x="16.360352" y="11" textLength="180.0293">process_template_response</tspan></text><path d="M 495 405 L 477 405 L 477 117 L 468 117 L 486 90 L 504 117 L 495 117 Z" fill="white" fill-opacity=".8"/><path d="M 495 405 L 477 405 L 477 117 L 468 117 L 486 90 L 504 117 L 495 117 Z" stroke="green" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(479 360.625) rotate(-90)" fill="green"><tspan font-family="Courier" font-size="12" font-weight="500" fill="green" x="55.515625" y="11" textLength="115.21875">process_response</tspan></text><path d="M 387 405 L 369 405 L 369 135 L 360 135 L 378 108 L 396 135 L 387 135 Z" fill="white" fill-opacity=".8"/><path d="M 387 405 L 369 405 L 369 135 L 360 135 L 378 108 L 396 135 L 387 135 Z" stroke="red" stroke-linecap="round" stroke-linejoin="round" stroke-width="1" stroke-dasharray="4,4"/><text transform="translate(371 362.875) rotate(-90)" fill="red"><tspan font-family="Courier" font-size="12" font-weight="500" fill="red" x="45.16504" y="11" textLength="122.41992">process_exception</tspan></text><g id="id33_Graphic"><path d="M 144 405 L 505.4694 405 L 513 418.5 L 505.4694 432 L 144 432 L 153 418.5 Z" fill="white"/><path d="M 144 405 L 505.4694 405 L 513 418.5 L 505.4694 432 L 144 432 L 153 418.5 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(149 411.5)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="500" fill="black" x="144.81543" y="11" textLength="69.36914">view function</tspan></text></g></g></g></svg> diff --git a/docs/topics/http/middleware.txt b/docs/topics/http/middleware.txt index 16fdace825..1f5414e95b 100644 --- a/docs/topics/http/middleware.txt +++ b/docs/topics/http/middleware.txt @@ -16,18 +16,128 @@ 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 is called. + + try: + response = get_response(request) + except Exception as e: + # Code to handle an exception that wasn't caught + # further up the chain, if desired. + ... + + # 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 with a ``__call__()`` method, 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 is called. + + try: + response = self.get_response(request) + except Exception as e: + # Code to handle an exception that wasn't caught + # further up the chain, if desired. + ... + + # Code to be executed for each request/response after + # the view is called. + + return response + +In both examples, the ``try``/``except`` isn't required if the middleware +doesn't need to handle any exceptions. If it is included, it should probably +catch something more specific than ``Exception``. + +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>` middleware. + +Middleware can live anywhere on your Python path. + +``__init__(get_response)`` +-------------------------- + +Middleware classes 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 get called once per request, + ``__init__()`` is called only *once*, when the Web server starts. + +.. versionchanged:: 1.10 + + In older versions, ``__init__`` was not called until the Web server + responded to its first request. + + If you want 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_CLASSES` list in your Django settings. +To activate a middleware component, add it to the :setting:`MIDDLEWARE` list in +your Django settings. -In :setting:`MIDDLEWARE_CLASSES`, each middleware component is represented by -a string: the full Python path to the middleware's class name. For example, +In :setting:`MIDDLEWARE`, each middleware component is represented by a string: +the full Python path to the middleware's class or function name. For example, here's the default value created by :djadmin:`django-admin startproject <startproject>`:: - MIDDLEWARE_CLASSES = [ + MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', @@ -37,13 +147,12 @@ here's the default value created by :djadmin:`django-admin startproject 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] -A Django installation doesn't require any middleware — -:setting:`MIDDLEWARE_CLASSES` can be empty, if you'd like — but it's strongly -suggested that you at least use +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_CLASSES` matters because a middleware can -depend on other middleware. For instance, +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 @@ -54,55 +163,21 @@ Hooks and application order =========================== During the request phase, before calling the view, Django applies middleware -in the order it's defined in :setting:`MIDDLEWARE_CLASSES`, top-down. Two -hooks are available: - -* :meth:`process_request` -* :meth:`process_view` - -During the response phase, after calling the view, middleware are applied in -reverse order, from the bottom up. Three hooks are available: - -* :meth:`process_exception` (only if the view raised an exception) -* :meth:`process_template_response` (only for template responses) -* :meth:`process_response` +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. -.. image:: _images/middleware.* - :alt: middleware application order - :width: 481 - :height: 409 +Middleware see only the changes made by middleware that run before it. A +middleware (and the view) is skipped entirely if a preceding middleware +short-circuits by returning a response without ever calling ``get_response``. +That response will only pass through the middleware that have already run. -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 -=========================== +Similarly, a middleware that sees the request on the way in and doesn't return +a response is guaranteed that it will always see the response on the way back +out. If the middleware also wants to see any uncaught exception on the way out, +it can wrap its call to ``get_response()`` in a ``try``/``except``. -Writing your own middleware is easy. Each middleware component is a single -Python class that defines one or more of the following methods: - -.. _request-middleware: - -``process_request()`` ---------------------- - -.. method:: process_request(request) - -``request`` is an :class:`~django.http.HttpRequest` object. - -``process_request()`` is called on each request, before Django decides which -view to execute. - -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_request()`` middleware, then, ``process_view()`` -middleware, and finally, the appropriate view. If it returns an -:class:`~django.http.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 :class:`~django.http.HttpResponse`, and -return the result. +Besides the middleware pattern described earlier, you can add two other methods +to class-based middleware: .. _view-middleware: @@ -125,14 +200,13 @@ 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 any other view or exception middleware, or the appropriate -view; it'll apply response middleware to that -:class:`~django.http.HttpResponse`, and return the result. +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 from ``process_request`` or ``process_view`` will prevent any + 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. @@ -170,41 +244,8 @@ called. Middleware are run in reverse order during the response phase, which includes ``process_template_response()``. -.. _response-middleware: - -``process_response()`` ----------------------- - -.. method:: process_response(request, response) - -``request`` is an :class:`~django.http.HttpRequest` object. ``response`` is -the :class:`~django.http.HttpResponse` or -:class:`~django.http.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 :class:`~django.http.HttpResponse` or -:class:`~django.http.StreamingHttpResponse` object. It could alter the given -``response``, or it could create and return a brand-new -:class:`~django.http.HttpResponse` or -:class:`~django.http.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 -:class:`~django.http.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 -:setting:`MIDDLEWARE_CLASSES` will be run first. - Dealing with streaming responses -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +================================ Unlike :class:`~django.http.HttpResponse`, :class:`~django.http.StreamingHttpResponse` does not have a ``content`` @@ -229,66 +270,62 @@ must test for streaming responses and adjust their behavior accordingly:: .. _exception-middleware: -``process_exception()`` ------------------------ +Exception middleware +==================== -.. method:: process_exception(request, exception) +A middleware that does some custom exception handling might looks like this:: -``request`` is an :class:`~django.http.HttpRequest` object. ``exception`` is an -``Exception`` object raised by the view function. + class ExceptionMiddleware(object): + def __init__(self, get_response): + self.get_response = get_response -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, default exception handling kicks in. + def __call__(self, request): + try: + response = self.get_response(request) + except Exception as e: + # Do something with the exception and possibly reraise it + # unless you wish to silence it. + ... + return response -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. +Middleware that wants to do something for all exception responses, an HTTP 404 +for example, need to both catch the appropriate exception (e.g. ``Http404``) +and look for regular responses with the status code of interest. You can +subclass :class:`~django.middleware.exception.ExceptionMiddleware` if you want +to transform exceptions into the appropriate response. -``__init__()`` --------------- +.. _upgrading-middleware: -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: +Upgrading pre-Django 1.10-style middleware +========================================== -* 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 starts. - -.. versionchanged:: 1.10 - - In older versions, ``__init__`` was not called until the Web server - responded to its first request. - -Marking middleware as unused -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. class:: django.utils.deprecation.MiddlewareMixin + :module: -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 :exc:`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 :setting:`DEBUG` is set to -``True``. +Django provides ``django.utils.deprecation.MiddlewareMixin`` to ease providing +the existing built-in middleware in both new-style and old-style forms and to +ease similar conversions of third-party middleware. -Guidelines ----------- +In most cases, this mixin will be sufficient to convert a middleware with +sufficient backwards-compatibility; the new short-circuiting semantics will be +harmless or even beneficial to the existing middleware. -* Middleware classes don't have to subclass anything. +In a few cases, a middleware class may need more invasive changes to adjust to +the new semantics. -* The middleware class can live anywhere on your Python path. All Django - cares about is that the :setting:`MIDDLEWARE_CLASSES` setting includes - the path to it. +For example, in the current request-handling logic, the handler transforms any +exception that passes through all ``process_exception`` middleware uncaught +into a response with appropriate status code (e.g. 404, 403, 400, or 500), and +then passes that response through the full chain of ``process_response`` +middleware. -* Feel free to look at :doc:`Django's available middleware - </ref/middleware>` for examples. +In new-style middleware, a given middleware only gets one shot at a given +response or uncaught exception "on the way out," and will see either a returned +response or an uncaught exception, but not both. -* If you write a middleware component that you think would be useful to - other people, contribute to the community! :doc:`Let us know - </internals/contributing/index>`, and we'll consider adding it to Django. +This means that certain middleware which want to do something with all 404 +responses (for example, the ``RedirectFallbackMiddleware`` and +``FlatpageFallbackMiddleware`` in ``django.contrib.redirects`` and +``django.contrib.flatpages``) now need to watch out for both a 404 response +and an uncaught ``Http404`` exception. They do this by subclassing +:class:`~django.middleware.exception.ExceptionMiddleware`. diff --git a/docs/topics/http/sessions.txt b/docs/topics/http/sessions.txt index 34a1b28b73..1a948397ae 100644 --- a/docs/topics/http/sessions.txt +++ b/docs/topics/http/sessions.txt @@ -18,13 +18,13 @@ Sessions are implemented via a piece of :doc:`middleware </ref/middleware>`. To enable session functionality, do the following: -* Edit the :setting:`MIDDLEWARE_CLASSES` setting and make sure - it contains ``'django.contrib.sessions.middleware.SessionMiddleware'``. - The default ``settings.py`` created by ``django-admin startproject`` - has ``SessionMiddleware`` activated. +* Edit the :setting:`MIDDLEWARE` setting and make sure it contains + ``'django.contrib.sessions.middleware.SessionMiddleware'``. The default + ``settings.py`` created by ``django-admin startproject`` has + ``SessionMiddleware`` activated. If you don't want to use sessions, you might as well remove the -``SessionMiddleware`` line from :setting:`MIDDLEWARE_CLASSES` and +``SessionMiddleware`` line from :setting:`MIDDLEWARE` and ``'django.contrib.sessions'`` from your :setting:`INSTALLED_APPS`. It'll save you a small bit of overhead. diff --git a/docs/topics/http/urls.txt b/docs/topics/http/urls.txt index 81dc4a0d94..ae5b714726 100644 --- a/docs/topics/http/urls.txt +++ b/docs/topics/http/urls.txt @@ -41,8 +41,8 @@ algorithm the system follows to determine which Python code to execute: 1. Django determines the root URLconf module to use. Ordinarily, this is the value of the :setting:`ROOT_URLCONF` setting, but if the incoming ``HttpRequest`` object has a :attr:`~django.http.HttpRequest.urlconf` - attribute (set by middleware :ref:`request processing <request-middleware>`), - its value will be used in place of the :setting:`ROOT_URLCONF` setting. + attribute (set by middleware), its value will be used in place of the + :setting:`ROOT_URLCONF` setting. 2. Django loads that Python module and looks for the variable ``urlpatterns``. This should be a Python list of :func:`django.conf.urls.url` diff --git a/docs/topics/i18n/timezones.txt b/docs/topics/i18n/timezones.txt index 8ea63f2908..674edc1a19 100644 --- a/docs/topics/i18n/timezones.txt +++ b/docs/topics/i18n/timezones.txt @@ -175,13 +175,14 @@ the most likely choices. Here's an example that stores the current timezone in the session. (It skips error handling entirely for the sake of simplicity.) -Add the following middleware to :setting:`MIDDLEWARE_CLASSES`:: +Add the following middleware to :setting:`MIDDLEWARE`:: import pytz from django.utils import timezone + from django.django.utils.deprecation import MiddlewareMixin - class TimezoneMiddleware(object): + class TimezoneMiddleware(MiddlewareMixin): def process_request(self, request): tzname = request.session.get('django_timezone') if tzname: diff --git a/docs/topics/i18n/translation.txt b/docs/topics/i18n/translation.txt index 43184a13a1..3f13021bc8 100644 --- a/docs/topics/i18n/translation.txt +++ b/docs/topics/i18n/translation.txt @@ -38,7 +38,7 @@ make some optimizations so as not to load the internationalization machinery. .. note:: Make sure you've activated translation for your project (the fastest way is - to check if :setting:`MIDDLEWARE_CLASSES` includes + to check if :setting:`MIDDLEWARE` includes :mod:`django.middleware.locale.LocaleMiddleware`). If you haven't yet, see :ref:`how-django-discovers-language-preference`. @@ -1422,7 +1422,7 @@ Django provides two mechanisms to internationalize URL patterns: Using either one of these features requires that an active language be set for each request; in other words, you need to have :class:`django.middleware.locale.LocaleMiddleware` in your - :setting:`MIDDLEWARE_CLASSES` setting. + :setting:`MIDDLEWARE` setting. Language prefix in URL patterns ------------------------------- @@ -2065,8 +2065,8 @@ prefer, then you also need to use the ``LocaleMiddleware``. It customizes content for each user. To use ``LocaleMiddleware``, add ``'django.middleware.locale.LocaleMiddleware'`` -to your :setting:`MIDDLEWARE_CLASSES` setting. Because middleware order -matters, you should follow these guidelines: +to your :setting:`MIDDLEWARE` setting. Because middleware order matters, follow +these guidelines: * Make sure it's one of the first middlewares installed. * It should come after ``SessionMiddleware``, because ``LocaleMiddleware`` @@ -2075,9 +2075,9 @@ matters, you should follow these guidelines: to resolve the requested URL. * If you use ``CacheMiddleware``, put ``LocaleMiddleware`` after it. -For example, your :setting:`MIDDLEWARE_CLASSES` might look like this:: +For example, your :setting:`MIDDLEWARE` might look like this:: - MIDDLEWARE_CLASSES = [ + MIDDLEWARE = [ 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.locale.LocaleMiddleware', 'django.middleware.common.CommonMiddleware', diff --git a/docs/topics/testing/tools.txt b/docs/topics/testing/tools.txt index 8db06c15a3..d2ef214c36 100644 --- a/docs/topics/testing/tools.txt +++ b/docs/topics/testing/tools.txt @@ -1182,7 +1182,7 @@ easy:: class MiddlewareTestCase(TestCase): def test_cache_middleware(self): - with self.modify_settings(MIDDLEWARE_CLASSES={ + with self.modify_settings(MIDDLEWARE={ 'append': 'django.middleware.cache.FetchFromCacheMiddleware', 'prepend': 'django.middleware.cache.UpdateCacheMiddleware', 'remove': [ @@ -1233,7 +1233,7 @@ decorator:: class MiddlewareTestCase(TestCase): - @modify_settings(MIDDLEWARE_CLASSES={ + @modify_settings(MIDDLEWARE={ 'append': 'django.middleware.cache.FetchFromCacheMiddleware', 'prepend': 'django.middleware.cache.UpdateCacheMiddleware', }) @@ -1245,7 +1245,7 @@ The decorator can also be applied to test case classes:: from django.test import TestCase, modify_settings - @modify_settings(MIDDLEWARE_CLASSES={ + @modify_settings(MIDDLEWARE={ 'append': 'django.middleware.cache.FetchFromCacheMiddleware', 'prepend': 'django.middleware.cache.UpdateCacheMiddleware', }) |
