Django之Middleware中间件(***)

Django之Middleware中间件(***)前端

  Middleware中间件,是在Django有HTTP请求时,在url去路由匹配以前的一道工序。是一道验证的功能。django

  在中间件中,有两个必有的方法。一个是接收到HTTP请求后要处理的。一个是处理完返回客户端时通过中间件要处理的方法。后端

  中间件就是一个类,可是要想应用这个类,是须要进行在Settings中的中间件列表中注册的。那既然是列表,那么中间件的执行顺序是有序的。函数

  这个类的两个必要的方法:process_request 和 process_response。url

  其中process_response是有return返回值的。而process_request是没有return返回值的。spa

  若是process_request有返回值,那么HTTP请求就不会再进入路由匹配,而是直接在中间件就返回啦。code

  可是Django的版本不一样,中间件也会有些许的区别:中间件

    Django1.10以后的版本:中间件的process_request有返回值,会直接用同中间件的process_response返回结果,而不是继续执行流程,去路由匹配views。在返回给用户应该的相应的结果。blog

    Django1.7或1.8以前的(含1.7/1.8):中间件的process_request有返回值,中间件的流程依旧会继续执行,它会找到最后的一个中间件,经过最后的中间件的process_response来返回,这个1.10的版本不一样,10是同中间件的process_response直接返回,1.8以前是用最后的process_response返回。资源

 

  中间件的编写实例:

  Settings中导入模块并添加md的中间件:

  md.py 中间件:

from django.utils.deprecation import MiddlewareMixin

class M1(MiddlewareMixin):
    def process_request(self,request):
        print("m1.process_request")

    def process_response(self,request,response):
        print("m1.process_response")
        return response

class M2(MiddlewareMixin):
    def process_request(self, request):
        print("m2.process_request")

    def process_response(self, request, response):
        print("m2.process_response")
        return response

  函数test:

def test(request):
    print("test")
    return HttpResponse("...")

  中间件的执行顺序,m1-m2-函数-m2-m1

  当md中的中间件加上process_view函数方法:

from django.utils.deprecation import MiddlewareMixin

class M1(MiddlewareMixin):
    def process_request(self,request):
        print("m1.process_request")

    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("m1.process_view")

    def process_response(self,request,response):
        print("m1.process_response")
        return response

class M2(MiddlewareMixin):
    def process_request(self, request):
        print("m2.process_request")

    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("m2.process_view")

    def process_response(self, request, response):
        print("m2.process_response")
        return response

 

  它的执行顺序会发生变化,他会在执行test函数并返回m1和m2的process_response以前,先去执行m1和m2的process_view。

  其缘由是:

    在执行完process_request的m1和m2后,又返回到了最开始的中间件,去顺序执行m1和m2的process_view。

    可是,在执行m1和m2的process_view这间,Django作了件路由匹配的事情,process_view的参数callback实际上是view_func的函数,好比咱们示例中的test,这个callback参数就是去匹配view视图中test函数的路由关系啦。

from django.utils.deprecation import MiddlewareMixin

class M1(MiddlewareMixin):
    def process_request(self,request):
        print("m1.process_request")

    def process_view(self,request,callback,callback_args,callback_kwargs):
        print(callback,callback_args,callback_kwargs)
        print("m1.process_view")

    def process_response(self,request,response):
        print("m1.process_response")
        return response

class M2(MiddlewareMixin):
    def process_request(self, request):
        print("m2.process_request")

    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("m2.process_view")

    def process_response(self, request, response):
        print("m2.process_response")
        return response

  在中间件中打印一下process_view的m1就能够看出,在中间件执行完m2后,会再一次回到原点,去匹配对应函数的路由。

 

   因此,在中间件中加上process_view方法后,中间件的执行顺序会有变化,而这中间作的事情就是去路由中匹配对应的函数。

  可是这里发生的都是中间件中作的事情,并无触及到真正的view函数,只有在中间件的功能的process_request都结束时,才会真正去执行view函数。

  但奇特的是:既然在process_view中就已经完成了路由的匹配,那么在中间件中是否是也能够直接执行view函数呐?

  毕竟callback就是那个view的函数呀!!!!哈哈哈,好奇特。什么鬼?

  在process_view中有两条路能够走,一条是继续往下走,执行下面的process_view,还有一条路是直接返回。

from django.utils.deprecation import MiddlewareMixin

class M1(MiddlewareMixin):
    def process_request(self,request):
        print("m1.process_request")

    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("m1.process_view")
        respones = callback(request,*callback_args,**callback_kwargs)
        return respones

    def process_response(self,request,response):
        print("m1.process_response")
        return response

class M2(MiddlewareMixin):
    def process_request(self, request):
        print("m2.process_request")

    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("m2.process_view")

    def process_response(self, request, response):
        print("m2.process_response")
        return response

  这里的process_view执行了m1的,并无执行m2的process_view。

 

   这里的流程是当m2的process_view有返回值时,它是再也不执行下一个中间件的,而不是去真正的view里执行,而是直接从最后的中间件开始返回。

 

   因此当process_view中有返回值的时候,它会执行完全部的process_response再返回。

  中间件中一共有5个方法:还有 process_template_response 和 process_exception 俩个方法。

  exception是异常相关的:

    正常状况下,这个函数方法是不会被执行的,只有在有异常报错的状况下,才会触发这个方法。

from django.utils.deprecation import MiddlewareMixin

class M1(MiddlewareMixin):
    def process_request(self,request):
        print("m1.process_request")

    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("m1.process_view")
        #respones = callback(request,*callback_args,**callback_kwargs)
        #return respones

    def process_response(self,request,response):
        print("m1.process_response")
        return response

    def process_exception(self,request,exception):
        print("m1.process_exception")

class M2(MiddlewareMixin):
    def process_request(self, request):
        print("m2.process_request")

    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("m2.process_view")

    def process_response(self, request, response):
        print("m2.process_response")
        return response

    def process_exception(self,request,exception):
        print("m2.process_exception")

  这里的view视图的test函数中我们让其故意出错

def test(request):
    print("test")
    int("asfafa")
    return HttpResponse("...")

  其结果是:

    前端报错:

    

 

   后端报错:    

 

   他执行的顺序是想执行完process_request和process_view,去view视图处理完发现异常后,交付的是m2和m1的process_exception。

  最后才在回到最后的中间件m2开始执行m2和m1的process_response。

  在m2的process_execption中捕获一下异常。

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

class M1(MiddlewareMixin):
    def process_request(self,request):
        print("m1.process_request")

    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("m1.process_view")
        # respones = callback(request,*callback_args,**callback_kwargs)
        # return respones

    def process_response(self,request,response):
        print("m1.process_response")
        return response

    def process_exception(self,request,exception):
        print("m1.process_exception")

class M2(MiddlewareMixin):
    def process_request(self, request):
        print("m2.process_request")

    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("m2.process_view")

    def process_response(self, request, response):
        print("m2.process_response")
        return response

    def process_exception(self,request,exception):
        print("m2.process_exception")
        return HttpResponse("错误了。。。")

  页面不在报错,而是有return的返回:

 

   它的输出的结果变成了:

 

   这里没有了m1的process_execption。因此,他在m2的process_execption中处理了以后,就不会在去m1的process_execption了,而是再回到m2的process_response顺序处理,并返回给用户。

  最后是process_template_response 方法的应用:

 

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

class M1(MiddlewareMixin):
    def process_request(self,request):
        print("m1.process_request")

    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("m1.process_view")
        # respones = callback(request,*callback_args,**callback_kwargs)
        # return respones

    def process_response(self,request,response):
        print("m1.process_response")
        return response

    def process_exception(self,request,exception):
        print("m1.process_exception")

    def process_template_response(self,request,response):
        print("m1.process_template_response")
        return response

class M2(MiddlewareMixin):
    def process_request(self, request):
        print("m2.process_request")

    def process_view(self,request,callback,callback_args,callback_kwargs):
        print("m2.process_view")

    def process_response(self, request, response):
        print("m2.process_response")
        return response

    def process_exception(self,request,exception):
        print("m2.process_exception")
        return HttpResponse("错误了。。。")

  结果是:

 

 这里没有异常的还,将再也不有process_execption,可是也没有process_template_response。

 这里没有process_template_response是由于要执行这个方法是要有render的返回值。

 也就是说:process_template_response的视图函数的返回值中,若是有render方法,才会被调用。

  好比:视图函数这样写:

class Foo:
    def __init__(self,req):
        self.req = req

    def render(self):
        return HttpResponse("...")

def test(request):
    obj = Foo(request)
    return obj

  那么process_template_response就会被执行。由于被执行的test函数有render方法。

总结中间件:

  中间件就是一个类,这个类里有5个方法,最为经常使用的是process_response和process_request。

  中间件是严格按照顺序有序的执行。

  中间件在何时会被应用到:

    当全部的请求都要统一作操做的时候,而在每一个函数里写是很浪费资源和时间的,因此就经过中间件的特性,当每一个请求来时都会必经的一个流程的地方作统一的处理,那就是中间件的做用,他在请求真正的去view视图函数中处理时以前,就能够加上咱们想要其作的事情。

    说的直白一点就是:对全部的请求或一部分请求作批量处理的。

 

----- END -----

相关文章
相关标签/搜索