>[success] # Django 中间件 ~~~ 所有的请求,先到中间插件过滤,过滤后进行url匹配,到对应的view方法,response返回给中间插件,中间插件层层返回给用户。根据这个描述我们可以画个图 ~~~ ![](https://box.kancloud.cn/0941286c3eac854b1c38adf6b50c8b62_583x309.png) * setting 中的图 ![](https://box.kancloud.cn/2e65d9d1a5839f1b4b124408b5b4924c_643x283.png) >[success] # 如何配置 >[danger] ##### 创建目录 ![](https://box.kancloud.cn/73f948016c8d31c6eeb9f60a18b0e16d_250x111.png) * * * * * <br> >[danger] ##### 导入中间件 ![](https://box.kancloud.cn/6ef3dcc174ceeb3d95befac736166a21_591x260.png) >[danger] ##### 编写中间件 ~~~ 1.知识点from django.utils.deprecation import MiddlewareMixin继承类 2.接受请求的方法名process_request() 3.返回响应的方法名process_response() 4.参数reuqest等同于view中的request ~~~ * 代码案例 ~~~ from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class test1(MiddlewareMixin): def process_request(self,request): print("1号请求") def process_response(self,request,response): print("1号响应") return response class test2(MiddlewareMixin): def process_request(self, request): print("2号请求") def process_response(self, request, response): print("2号响应") return response ~~~ * 打印结果 ~~~ 1号请求 2号请求 view响应 2号响应 1号响应 ~~~ >[danger] ##### 发现条件不满足时 ![](https://box.kancloud.cn/26899d37b3683b877ba7ff07243f1083_603x287.png) 当第一个过滤器发现已经不满足,过滤筛选项时,可以利用HttpResponse,直接不经过views层 ~~~ from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class first(MiddlewareMixin): def process_request(self,request): print(request.META['REMOTE_ADDR']) return HttpResponse('你没有权限') def process_response(self,request,response): print("1号响应") return response ~~~ >[success] # 参数流程 >[danger] ##### 统计模板运行时间 func 代指运行函数 ~~~ from django.utils.deprecation import MiddlewareMixin from django.urls import reverse class TimeItMiddleware(MiddlewareMixin): def process_request(self, request): return def process_view(self, request, func, *args, **kwargs): if request.path != reverse('index'): return None start = time.time() response = func(request) costed = time.time() - start print('{:.2f}s'.format(costed)) return response def process_exception(self, request, exception): pass def process_template_response(self, request, response): return response def process_response(self, request, response): return response ~~~ >[danger] ##### process_request ~~~ 一个请求来到middelware层,进入的第一个方法。一般情况我们可以在这里做一 些校验,比如用户登录,或者HTTP中是否有认证头之类的验证。这个方法需要两 种返回值,HttpResponse或者None,如果返回HttpResponse,那么接下来的 处理方法只会执行process_response,其他的方法将不会被执行。这里需要注意 的是,如果你的middleware在settings配置的MIDDLEWARE_CLASS的第一个的 话,那么剩下的middleware也不会被执行。另外一个返回值是None,如果返回 None,那么Django会继续执行其他的方法。 ~~~ >[danger] ##### process_view ~~~ 这个方法是在process_request之后执行的,参数如上面代码所示,其中的func 就是我们将要执行的view方法,因此我们要统计一个view的执行时间,可以在这 里来做。它的返回值跟process_request一样,HttpResponse/None,逻辑也是 一样。如果返回None,那么Django会帮你执行view函数,从而得到最终的 Response。 ~~~ >[danger] ##### process_template_response ~~~ 执行完上面的方法,并且Django帮忙我们执行完view之后,拿到最终的 response,如果是使用了模板的Response(是指通过return render(request, 'index.html', context={})的方式返回Response,就会来到这个方法中。这个方 法中我们可以对response做一下操作,比如Content-Type设置,或者其他 HEADER的修改/增加。 ~~~ >[danger] ##### process_response ~~~ 当所有流程都处理完毕,就来到了这个方法,这个方法的逻辑跟 process_template_response是完全一样的。只是process_template_response 是针对带有模板的response的处理。 ~~~ >[danger] ##### process_exception ~~~ 上面的所有处理方法是按顺序介绍的,而这个不太一样。只有在发生异常时,才 会进入到这个方法。哪个阶段发生的异常呢?可以简单的理解为在将要调用的 view中出现异常(就是在process_view的func函数中)或者返回的模板 Response在render时发生的异常,会进入到这个方法中。但是需要注意的是, 如果你在process_view中手动调用了func,就像我们上面做的那样,那就不会触 发process_exception了。这个方法接收到异常之后,可以选择处理异常,然后 返回一个含有异常信息的HttpResponse,或者直接返回None,不处理,这种情 况Django会使用自己的异常模板。 ~~~