{"title":"中间件","version":"2.1","locale":"zh-hans","docname":"topics/http/middleware","url":"/zh-hans/2.1/topics/http/middleware/","canonical":"https://djangodocs.dev/zh-hans/2.1/topics/http/middleware/","summary":"中间件是 Django 请求/响应处理的钩子框架。它是一个轻量级的、低级的“插件”系统，用于全局改变 Django 的输入或输出。 每个中间件组件负责做一些特定的功能。例如，Django 包含一个中间件组件 AuthenticationMiddleware ，它使用会话将用户与请求关联起来。…","html":"<h1>中间件<a class=\"heading-anchor\" href=\"#middleware\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>中间件是 Django 请求/响应处理的钩子框架。它是一个轻量级的、低级的“插件”系统，用于全局改变 Django 的输入或输出。</p>\n<p>每个中间件组件负责做一些特定的功能。例如，Django 包含一个中间件组件 <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/middleware/#django.contrib.auth.middleware.AuthenticationMiddleware\" title=\"django.contrib.auth.middleware.AuthenticationMiddleware\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AuthenticationMiddleware</span></code></a>，它使用会话将用户与请求关联起来。</p>\n<p>他的文档解释了中间件是如何工作的，如何激活中间件，以及如何编写自己的中间件。Django 具有一些内置的中间件，你可以直接使用。它们被记录在 <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/middleware/\"><span class=\"doc\">built-in middleware reference</span></a> 中。</p>\n<section id=\"writing-your-own-middleware\">\n<h2>编写自己的中间件<a class=\"heading-anchor\" href=\"#writing-your-own-middleware\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>中间件工厂是一个可调用的程序，它接受 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_response</span></code> 可调用并返回中间件。中间件是可调用的，它接受请求并返回响应，就像视图一样。</p>\n<p>中间件可以被写成这样的函数：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">simple_middleware</span><span class=\"p\">(</span><span class=\"n\">get_response</span><span class=\"p\">):</span>\n    <span class=\"c1\"># One-time configuration and initialization.</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">middleware</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Code to be executed for each request before</span>\n        <span class=\"c1\"># the view (and later middleware) are called.</span>\n\n        <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"n\">get_response</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">)</span>\n\n        <span class=\"c1\"># Code to be executed for each request/response after</span>\n        <span class=\"c1\"># the view is called.</span>\n\n        <span class=\"k\">return</span> <span class=\"n\">response</span>\n\n    <span class=\"k\">return</span> <span class=\"n\">middleware</span>\n</code></pre></div>\n<p>或者它可以写成一个类，它的实例是可调用的，如下：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">SimpleMiddleware</span><span class=\"p\">:</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">get_response</span><span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">get_response</span> <span class=\"o\">=</span> <span class=\"n\">get_response</span>\n        <span class=\"c1\"># One-time configuration and initialization.</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__call__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Code to be executed for each request before</span>\n        <span class=\"c1\"># the view (and later middleware) are called.</span>\n\n        <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">get_response</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">)</span>\n\n        <span class=\"c1\"># Code to be executed for each request/response after</span>\n        <span class=\"c1\"># the view is called.</span>\n\n        <span class=\"k\">return</span> <span class=\"n\">response</span>\n</code></pre></div>\n<p>Django 提供的 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_response</span></code> 响应可能是实际视图（如果这是最后列出的中间件），或者它可能是链中的下一个中间件。不需要知道或关心当前的中间件到底是什么，它只是代表了下一步的内容。</p>\n<p>以上是一个轻微的简化——链中最后一个中间件调用的 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_response</span></code> 可不是实际视图，而是处理程序的包装方法，它负责应用 <a class=\"reference internal\" href=\"#view-middleware\"><span class=\"std std-ref\">view middleware</span></a>，调用具有适当URL参数的视图，并应用 <a class=\"reference internal\" href=\"#template-response-middleware\"><span class=\"std std-ref\">template-response</span></a> 和 <a class=\"reference internal\" href=\"#exception-middleware\"><span class=\"std std-ref\">exception</span></a> 中间件。</p>\n<p>中间件可以放在 Python 路径上的任何地方。</p>\n<section id=\"init-get-response\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">__init__(get_response)</span></code><a class=\"heading-anchor\" href=\"#init-get-response\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>中间件工厂必须接受 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_response</span></code> 参数。还可以初始化中间件的一些全局状态。记住两个注意事项：</p>\n<ul class=\"simple\">\n<li><p>Django仅用 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_response</span></code> 参数初始化您的中间件，因此不能定义 <code class=\"docutils literal notranslate\"><span class=\"pre\">__init__()</span></code> ，因为需要其他参数。</p></li>\n<li><p>与每次请求调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">__call__()</span></code> 方法不同，当 Web 服务器启动时，<code class=\"docutils literal notranslate\"><span class=\"pre\">__init__()</span></code> 只被称为*一次*。</p></li>\n</ul>\n</section>\n<section id=\"marking-middleware-as-unused\">\n<h3>标记未使用的中间件<a class=\"heading-anchor\" href=\"#marking-middleware-as-unused\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>在启动时确定是否应该使用一个中间件有时是有用的。在这些情况下，您的中间件的 <code class=\"docutils literal notranslate\"><span class=\"pre\">__init__()</span></code> 方法可能会引发 <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/exceptions/#django.core.exceptions.MiddlewareNotUsed\" title=\"django.core.exceptions.MiddlewareNotUsed\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">MiddlewareNotUsed</span></code></a>。Django 将从中间件进程中删除该中间件，并将调试消息记录到 <a class=\"reference internal\" href=\"/zh-hans/2.1/topics/logging/#django-request-logger\"><span class=\"std std-ref\">django.request</span></a> 日志：设置 <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/settings/#std-setting-DEBUG\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DEBUG</span></code></a> 为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>。</p>\n</section>\n</section>\n<section id=\"activating-middleware\">\n<h2>激活中间件<a class=\"heading-anchor\" href=\"#activating-middleware\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>若要激活中间件组件，请将其添加到 Django 设置中的 <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">MIDDLEWARE</span></code></a> 列表中。</p>\n<p>在 <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">MIDDLEWARE</span></code></a> 中，每个中间件组件由字符串表示：指向中间件工厂的类或函数名的完整 Python 路径。例如，这里创建的默认值是 <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/django-admin/#django-admin-startproject\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">django-admin</span> <span class=\"pre\">startproject</span></code></a>：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">MIDDLEWARE</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"s1\">&#39;django.middleware.security.SecurityMiddleware&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.sessions.middleware.SessionMiddleware&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.middleware.common.CommonMiddleware&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.middleware.csrf.CsrfViewMiddleware&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.middleware.AuthenticationMiddleware&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.messages.middleware.MessageMiddleware&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.middleware.clickjacking.XFrameOptionsMiddleware&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>Django 安装不需要任何中间件——如果您愿意的话，<a class=\"reference internal\" href=\"/zh-hans/2.1/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">MIDDLEWARE</span></code></a> 可以为空——但是强烈建议您至少使用 <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/middleware/#django.middleware.common.CommonMiddleware\" title=\"django.middleware.common.CommonMiddleware\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">CommonMiddleware</span></code></a>。</p>\n<p><a class=\"reference internal\" href=\"/zh-hans/2.1/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">MIDDLEWARE</span></code></a> 的顺序很重要，因为中间件会依赖其他中间件。例如：类 <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/middleware/#django.contrib.auth.middleware.AuthenticationMiddleware\" title=\"django.contrib.auth.middleware.AuthenticationMiddleware\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AuthenticationMiddleware</span></code></a> 在会话中存储经过身份验证的用户；因此，它必须在 <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/middleware/#django.contrib.sessions.middleware.SessionMiddleware\" title=\"django.contrib.sessions.middleware.SessionMiddleware\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SessionMiddleware</span></code></a> 后面运行 。中间件。Session中间件。请参阅 <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/middleware/#middleware-ordering\"><span class=\"std std-ref\">Middleware ordering</span></a> ，用于一些关于 Django 中间件类排序的常见提示。</p>\n</section>\n<section id=\"middleware-order-and-layering\">\n<h2>中间件顺序与分层<a class=\"heading-anchor\" href=\"#middleware-order-and-layering\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>在请求阶段，在调用视图之前，Django 按照定义的顺序应用中间件 <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">MIDDLEWARE</span></code></a>，自顶向下。</p>\n<p>你可以把它想象成一个洋葱：每个中间件类都是一个“层”，它覆盖了洋葱的核心。如果请求通过洋葱的所有层（每一个调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_response</span></code> ）以将请求传递到下一层，一直到内核的视图，那么响应将在返回的过程中通过每个层（以相反的顺序）。</p>\n<p>If one of the layers decides to short-circuit and return a response without\never calling its <code class=\"docutils literal notranslate\"><span class=\"pre\">get_response</span></code>, none of the layers of the onion inside that\nlayer (including the view) will see the request or the response. The response\nwill only return through the same layers that the request passed in through.</p>\n</section>\n<section id=\"other-middleware-hooks\">\n<h2>Other middleware hooks<a class=\"heading-anchor\" href=\"#other-middleware-hooks\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Besides the basic request/response middleware pattern described earlier, you\ncan add three other special methods to class-based middleware:</p>\n<section id=\"process-view\">\n<span id=\"view-middleware\"></span><h3><code class=\"docutils literal notranslate\"><span class=\"pre\">process_view()</span></code><a class=\"heading-anchor\" href=\"#process-view\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"process_view\">\n<span class=\"sig-name descname\"><span class=\"pre\">process_view</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">request</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">view_func</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">view_args</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">view_kwargs</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#process_view\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">request</span></code> is an <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/request-response/#django.http.HttpRequest\" title=\"django.http.HttpRequest\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpRequest</span></code></a> object. <code class=\"docutils literal notranslate\"><span class=\"pre\">view_func</span></code> is\nthe Python function that Django is about to use. (It's the actual function\nobject, not the name of the function as a string.) <code class=\"docutils literal notranslate\"><span class=\"pre\">view_args</span></code> is a list of\npositional arguments that will be passed to the view, and <code class=\"docutils literal notranslate\"><span class=\"pre\">view_kwargs</span></code> is a\ndictionary of keyword arguments that will be passed to the view. Neither\n<code class=\"docutils literal notranslate\"><span class=\"pre\">view_args</span></code> nor <code class=\"docutils literal notranslate\"><span class=\"pre\">view_kwargs</span></code> include the first view argument\n(<code class=\"docutils literal notranslate\"><span class=\"pre\">request</span></code>).</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">process_view()</span></code> is called just before Django calls the view.</p>\n<p>It should return either <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> or an <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponse</span></code></a>\nobject. If it returns <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>, Django will continue processing this request,\nexecuting any other <code class=\"docutils literal notranslate\"><span class=\"pre\">process_view()</span></code> middleware and, then, the appropriate\nview. If it returns an <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponse</span></code></a> object, Django won't\nbother calling the appropriate view; it'll apply response middleware to that\n<a class=\"reference internal\" href=\"/zh-hans/2.1/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponse</span></code></a> and return the result.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>Accessing <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/request-response/#django.http.HttpRequest.POST\" title=\"django.http.HttpRequest.POST\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">request.POST</span></code></a> inside\nmiddleware before the view runs or in <code class=\"docutils literal notranslate\"><span class=\"pre\">process_view()</span></code> will prevent any\nview running after the middleware from being able to <a class=\"reference internal\" href=\"/zh-hans/2.1/topics/http/file-uploads/#modifying-upload-handlers-on-the-fly\"><span class=\"std std-ref\">modify the\nupload handlers for the request</span></a>,\nand should normally be avoided.</p>\n<p>The <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/middleware/#django.middleware.csrf.CsrfViewMiddleware\" title=\"django.middleware.csrf.CsrfViewMiddleware\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">CsrfViewMiddleware</span></code></a> class can be\nconsidered an exception, as it provides the\n<a class=\"reference internal\" href=\"/zh-hans/2.1/ref/csrf/#django.views.decorators.csrf.csrf_exempt\" title=\"django.views.decorators.csrf.csrf_exempt\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">csrf_exempt()</span></code></a> and\n<a class=\"reference internal\" href=\"/zh-hans/2.1/ref/csrf/#django.views.decorators.csrf.csrf_protect\" title=\"django.views.decorators.csrf.csrf_protect\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">csrf_protect()</span></code></a> decorators which allow\nviews to explicitly control at what point the CSRF validation should occur.</p>\n</aside>\n</section>\n<section id=\"process-exception\">\n<span id=\"exception-middleware\"></span><h3><code class=\"docutils literal notranslate\"><span class=\"pre\">process_exception()</span></code><a class=\"heading-anchor\" href=\"#process-exception\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"process_exception\">\n<span class=\"sig-name descname\"><span class=\"pre\">process_exception</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">request</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">exception</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#process_exception\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">request</span></code> is an <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/request-response/#django.http.HttpRequest\" title=\"django.http.HttpRequest\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpRequest</span></code></a> object. <code class=\"docutils literal notranslate\"><span class=\"pre\">exception</span></code> is an\n<code class=\"docutils literal notranslate\"><span class=\"pre\">Exception</span></code> object raised by the view function.</p>\n<p>Django calls <code class=\"docutils literal notranslate\"><span class=\"pre\">process_exception()</span></code> when a view raises an exception.\n<code class=\"docutils literal notranslate\"><span class=\"pre\">process_exception()</span></code> should return either <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> or an\n<a class=\"reference internal\" href=\"/zh-hans/2.1/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponse</span></code></a> object. If it returns an\n<a class=\"reference internal\" href=\"/zh-hans/2.1/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponse</span></code></a> object, the template response and response\nmiddleware will be applied and the resulting response returned to the\nbrowser. Otherwise, <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/views/#error-views\"><span class=\"std std-ref\">default exception handling</span></a> kicks in.</p>\n<p>Again, middleware are run in reverse order during the response phase, which\nincludes <code class=\"docutils literal notranslate\"><span class=\"pre\">process_exception</span></code>. If an exception middleware returns a response,\nthe <code class=\"docutils literal notranslate\"><span class=\"pre\">process_exception</span></code> methods of the middleware classes above that\nmiddleware won't be called at all.</p>\n</section>\n<section id=\"process-template-response\">\n<span id=\"template-response-middleware\"></span><h3><code class=\"docutils literal notranslate\"><span class=\"pre\">process_template_response()</span></code><a class=\"heading-anchor\" href=\"#process-template-response\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"process_template_response\">\n<span class=\"sig-name descname\"><span class=\"pre\">process_template_response</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">request</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">response</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#process_template_response\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">request</span></code> is an <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/request-response/#django.http.HttpRequest\" title=\"django.http.HttpRequest\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpRequest</span></code></a> object. <code class=\"docutils literal notranslate\"><span class=\"pre\">response</span></code> is\nthe <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/template-response/#django.template.response.TemplateResponse\" title=\"django.template.response.TemplateResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponse</span></code></a> object (or equivalent)\nreturned by a Django view or by a middleware.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">process_template_response()</span></code> is called just after the view has finished\nexecuting, if the response instance has a <code class=\"docutils literal notranslate\"><span class=\"pre\">render()</span></code> method, indicating that\nit is a <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/template-response/#django.template.response.TemplateResponse\" title=\"django.template.response.TemplateResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponse</span></code></a> or equivalent.</p>\n<p>It must return a response object that implements a <code class=\"docutils literal notranslate\"><span class=\"pre\">render</span></code> method. It could\nalter the given <code class=\"docutils literal notranslate\"><span class=\"pre\">response</span></code> by changing <code class=\"docutils literal notranslate\"><span class=\"pre\">response.template_name</span></code> and\n<code class=\"docutils literal notranslate\"><span class=\"pre\">response.context_data</span></code>, or it could create and return a brand-new\n<a class=\"reference internal\" href=\"/zh-hans/2.1/ref/template-response/#django.template.response.TemplateResponse\" title=\"django.template.response.TemplateResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponse</span></code></a> or equivalent.</p>\n<p>You don't need to explicitly render responses -- responses will be\nautomatically rendered once all template response middleware has been\ncalled.</p>\n<p>Middleware are run in reverse order during the response phase, which\nincludes <code class=\"docutils literal notranslate\"><span class=\"pre\">process_template_response()</span></code>.</p>\n</section>\n</section>\n<section id=\"dealing-with-streaming-responses\">\n<h2>Dealing with streaming responses<a class=\"heading-anchor\" href=\"#dealing-with-streaming-responses\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Unlike <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponse</span></code></a>,\n<a class=\"reference internal\" href=\"/zh-hans/2.1/ref/request-response/#django.http.StreamingHttpResponse\" title=\"django.http.StreamingHttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">StreamingHttpResponse</span></code></a> does not have a <code class=\"docutils literal notranslate\"><span class=\"pre\">content</span></code>\nattribute. As a result, middleware can no longer assume that all responses\nwill have a <code class=\"docutils literal notranslate\"><span class=\"pre\">content</span></code> attribute. If they need access to the content, they\nmust test for streaming responses and adjust their behavior accordingly:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">if</span> <span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">streaming</span><span class=\"p\">:</span>\n    <span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">streaming_content</span> <span class=\"o\">=</span> <span class=\"n\">wrap_streaming_content</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">streaming_content</span><span class=\"p\">)</span>\n<span class=\"k\">else</span><span class=\"p\">:</span>\n    <span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">content</span> <span class=\"o\">=</span> <span class=\"n\">alter_content</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">content</span><span class=\"p\">)</span>\n</code></pre></div>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">streaming_content</span></code> should be assumed to be too large to hold in memory.\nResponse middleware may wrap it in a new generator, but must not consume\nit. Wrapping is typically implemented as follows:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">wrap_streaming_content</span><span class=\"p\">(</span><span class=\"n\">content</span><span class=\"p\">):</span>\n    <span class=\"k\">for</span> <span class=\"n\">chunk</span> <span class=\"ow\">in</span> <span class=\"n\">content</span><span class=\"p\">:</span>\n        <span class=\"k\">yield</span> <span class=\"n\">alter_content</span><span class=\"p\">(</span><span class=\"n\">chunk</span><span class=\"p\">)</span>\n</code></pre></div>\n</aside>\n</section>\n<section id=\"exception-handling\">\n<h2>异常处理<a class=\"heading-anchor\" href=\"#exception-handling\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django automatically converts exceptions raised by the view or by middleware\ninto an appropriate HTTP response with an error status code. <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/views/#error-views\"><span class=\"std std-ref\">Certain\nexceptions</span></a> are converted to 4xx status codes, while an unknown\nexception is converted to a 500 status code.</p>\n<p>This conversion takes place before and after each middleware (you can think of\nit as the thin film in between each layer of the onion), so that every\nmiddleware can always rely on getting some kind of HTTP response back from\ncalling its <code class=\"docutils literal notranslate\"><span class=\"pre\">get_response</span></code> callable. Middleware don't need to worry about\nwrapping their call to <code class=\"docutils literal notranslate\"><span class=\"pre\">get_response</span></code> in a <code class=\"docutils literal notranslate\"><span class=\"pre\">try/except</span></code> and handling an\nexception that might have been raised by a later middleware or the view. Even\nif the very next middleware in the chain raises an\n<a class=\"reference internal\" href=\"/zh-hans/2.1/topics/http/views/#django.http.Http404\" title=\"django.http.Http404\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Http404</span></code></a> exception, for example, your middleware won't see\nthat exception; instead it will get an <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponse</span></code></a>\nobject with a <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/request-response/#django.http.HttpResponse.status_code\" title=\"django.http.HttpResponse.status_code\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">status_code</span></code></a> of 404.</p>\n</section>\n<section id=\"upgrading-pre-django-1-10-style-middleware\">\n<span id=\"upgrading-middleware\"></span><h2>Upgrading pre-Django 1.10-style middleware<a class=\"heading-anchor\" href=\"#upgrading-pre-django-1-10-style-middleware\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.utils.deprecation.MiddlewareMixin\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-prename descclassname\"><span class=\"pre\">django.utils.deprecation.</span></span><span class=\"sig-name descname\"><span class=\"pre\">MiddlewareMixin</span></span><a class=\"heading-anchor\" href=\"#django.utils.deprecation.MiddlewareMixin\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Django provides <code class=\"docutils literal notranslate\"><span class=\"pre\">django.utils.deprecation.MiddlewareMixin</span></code> to ease creating\nmiddleware classes that are compatible with both <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">MIDDLEWARE</span></code></a> and the\nold <code class=\"docutils literal notranslate\"><span class=\"pre\">MIDDLEWARE_CLASSES</span></code>. All middleware classes included with Django\nare compatible with both settings.</p>\n<p>The mixin provides an <code class=\"docutils literal notranslate\"><span class=\"pre\">__init__()</span></code> method that accepts an optional\n<code class=\"docutils literal notranslate\"><span class=\"pre\">get_response</span></code> argument and stores it in <code class=\"docutils literal notranslate\"><span class=\"pre\">self.get_response</span></code>.</p>\n<p>The <code class=\"docutils literal notranslate\"><span class=\"pre\">__call__()</span></code> method:</p>\n<ol class=\"arabic simple\">\n<li><p>Calls <code class=\"docutils literal notranslate\"><span class=\"pre\">self.process_request(request)</span></code> (if defined).</p></li>\n<li><p>Calls <code class=\"docutils literal notranslate\"><span class=\"pre\">self.get_response(request)</span></code> to get the response from later\nmiddleware and the view.</p></li>\n<li><p>Calls <code class=\"docutils literal notranslate\"><span class=\"pre\">self.process_response(request,</span> <span class=\"pre\">response)</span></code> (if defined).</p></li>\n<li><p>Returns the response.</p></li>\n</ol>\n<p>If used with <code class=\"docutils literal notranslate\"><span class=\"pre\">MIDDLEWARE_CLASSES</span></code>, the <code class=\"docutils literal notranslate\"><span class=\"pre\">__call__()</span></code> method will\nnever be used; Django calls <code class=\"docutils literal notranslate\"><span class=\"pre\">process_request()</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">process_response()</span></code>\ndirectly.</p>\n<p>In most cases, inheriting from this mixin will be sufficient to make an\nold-style middleware compatible with the new system with sufficient\nbackwards-compatibility. The new short-circuiting semantics will be harmless or\neven beneficial to the existing middleware. In a few cases, a middleware class\nmay need some changes to adjust to the new semantics.</p>\n<p>These are the behavioral differences between using <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">MIDDLEWARE</span></code></a> and\n<code class=\"docutils literal notranslate\"><span class=\"pre\">MIDDLEWARE_CLASSES</span></code>:</p>\n<ol class=\"arabic simple\">\n<li><p>Under <code class=\"docutils literal notranslate\"><span class=\"pre\">MIDDLEWARE_CLASSES</span></code>, every middleware will always have its\n<code class=\"docutils literal notranslate\"><span class=\"pre\">process_response</span></code> method called, even if an earlier middleware\nshort-circuited by returning a response from its <code class=\"docutils literal notranslate\"><span class=\"pre\">process_request</span></code>\nmethod. Under <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">MIDDLEWARE</span></code></a>, middleware behaves more like an onion:\nthe layers that a response goes through on the way out are the same layers\nthat saw the request on the way in. If a middleware short-circuits, only\nthat middleware and the ones before it in <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">MIDDLEWARE</span></code></a> will see the\nresponse.</p></li>\n<li><p>Under <code class=\"docutils literal notranslate\"><span class=\"pre\">MIDDLEWARE_CLASSES</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">process_exception</span></code> is applied to\nexceptions raised from a middleware <code class=\"docutils literal notranslate\"><span class=\"pre\">process_request</span></code> method. Under\n<a class=\"reference internal\" href=\"/zh-hans/2.1/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">MIDDLEWARE</span></code></a>, <code class=\"docutils literal notranslate\"><span class=\"pre\">process_exception</span></code> applies only to exceptions\nraised from the view (or from the <code class=\"docutils literal notranslate\"><span class=\"pre\">render</span></code> method of a\n<a class=\"reference internal\" href=\"/zh-hans/2.1/ref/template-response/#django.template.response.TemplateResponse\" title=\"django.template.response.TemplateResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponse</span></code></a>). Exceptions raised from\na middleware are converted to the appropriate HTTP response and then passed\nto the next middleware.</p></li>\n<li><p>Under <code class=\"docutils literal notranslate\"><span class=\"pre\">MIDDLEWARE_CLASSES</span></code>, if a <code class=\"docutils literal notranslate\"><span class=\"pre\">process_response</span></code> method raises\nan exception, the <code class=\"docutils literal notranslate\"><span class=\"pre\">process_response</span></code> methods of all earlier middleware are\nskipped and a <code class=\"docutils literal notranslate\"><span class=\"pre\">500</span> <span class=\"pre\">Internal</span> <span class=\"pre\">Server</span> <span class=\"pre\">Error</span></code> HTTP response is always\nreturned (even if the exception raised was e.g. an\n<a class=\"reference internal\" href=\"/zh-hans/2.1/topics/http/views/#django.http.Http404\" title=\"django.http.Http404\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Http404</span></code></a>). Under <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">MIDDLEWARE</span></code></a>, an exception\nraised from a middleware will immediately be converted to the appropriate\nHTTP response, and then the next middleware in line will see that\nresponse. Middleware are never skipped due to a middleware raising an\nexception.</p></li>\n</ol>\n</section>","rootId":"middleware","toc":[{"title":"编写自己的中间件","anchor":"writing-your-own-middleware","children":[{"title":"__init__(get_response)","anchor":"init-get-response","children":[]},{"title":"标记未使用的中间件","anchor":"marking-middleware-as-unused","children":[]}]},{"title":"激活中间件","anchor":"activating-middleware","children":[]},{"title":"中间件顺序与分层","anchor":"middleware-order-and-layering","children":[]},{"title":"Other middleware hooks","anchor":"other-middleware-hooks","children":[{"title":"process_view()","anchor":"process-view","children":[]},{"title":"process_exception()","anchor":"process-exception","children":[]},{"title":"process_template_response()","anchor":"process-template-response","children":[]}]},{"title":"Dealing with streaming responses","anchor":"dealing-with-streaming-responses","children":[]},{"title":"异常处理","anchor":"exception-handling","children":[]},{"title":"Upgrading pre-Django 1.10-style middleware","anchor":"upgrading-pre-django-1-10-style-middleware","children":[]}],"breadcrumbs":[{"docname":"topics/index","title":"Using Django","url":"/zh-hans/2.1/topics/"},{"docname":"topics/http/index","title":"处理 HTTP 请求","url":"/zh-hans/2.1/topics/http/"}],"prev":{"docname":"topics/http/generic-views","title":"通用视图","url":"/zh-hans/2.1/topics/http/generic-views/"},"next":{"docname":"topics/http/sessions","title":"如何使用会话","url":"/zh-hans/2.1/topics/http/sessions/"},"formats":{"html":"/zh-hans/2.1/topics/http/middleware/","markdown":"/zh-hans/2.1/topics/http/middleware.md","json":"/zh-hans/2.1/topics/http/middleware.json"},"source":"https://github.com/django/django/blob/stable/2.1.x/docs/topics/http/middleware.txt","official":"https://docs.djangoproject.com/zh-hans/2.1/topics/http/middleware/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0"],"inLocales":["en","zh-hans","fr","ja","id","pt-br","ko","es","el","pl"]}