• Django之Middleware中间件(***)


    Django之Middleware中间件(***)

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

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

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

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

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

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

      但是Django的版本不同,中间件也会有些许的区别:

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

        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 -----

  • 相关阅读:
    git使用教程指南
    关于px,分辨率,ppi的辨析
    js事件循环机制辨析
    promise基于reduce实现队列消息
    js 文件下载进度监控
    sql表与表之间的数据操作
    微信退款证书使用c#
    微信小程序支付C#后端源码
    微信小程序支付前端源码
    未能加载文件或程序集“System.Web.Http.WebHost, Version=4.0.0.0, ”或它的某一个依赖项。系统找不到指定的文件。
  • 原文地址:https://www.cnblogs.com/george92/p/11434433.html
Copyright © 2020-2023  润新知