• Django之中间件


     

    Django中间件

    在http请求 到达视图函数之前   和视图函数return之后,django会根据自己的规则在合适的时机执行中间件中相应的方法。

    中间件的执行流程

    1、执行完所有的request方法 到达视图函数。

    2、执行中间件的其他方法

    2、经过所有response方法 返回客户端。

    注意:如果在其中1个中间件里 request方法里 return了值,就会执行当前中间的response方法,返回给用户 然后 报错。。不会再执行下一个中间件。

    自定义中间件 

    1.在project下随便创建一个py文件

    from django.utils.deprecation import MiddlewareMixin
    class Middle1(MiddlewareMixin):
        def process_request(self,request):
            print("来了")
        def process_response(self, request,response):
            print('走了')
    View Code

    2、在setings文件中 注册这个 py文件

    django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'M1.Middle1',
    ]
    View Code

     执行结果

    为啥报错了呢?

    因为 自定义的中间件response方法没有return,交给下一个中间件,导致http请求中断了!!!

    中间件注意事项

    1.自定义的中间件process_request方法不要return, 因为返回之后中间件不再往下执行,导致 http请求到达不了视图层,request在视图之前执行!

    2.自定义的中间件process_response方法最后一定要return执行完了当前中间件response信息还要传递给下一个中间件;

    from django.utils.deprecation import MiddlewareMixin
    class Middle1(MiddlewareMixin):
        def process_request(self,request):
            print("来了") #不用return Django内部自动帮我们传递
        def process_response(self, request,response):
            print('走了')
            return response #执行完了这个中间件一定要 传递给下一个中间件
    View Code

     

     

    中间件(类)中5种方法

    中间件中可以定义5个方法,分别是:

    • process_request(self,request)
    • process_view(self, request, callback, callback_args, callback_kwargs)
    • process_template_response(self,request,response)
    • process_exception(self, request, exception)
    • process_response(self, request, response

    1、 process_view(self, request, callback, callback_args, callback_kwargs)方法介绍

    (1)执行完所有中间件的request方法‘

    (2)url匹配成功

    (3)拿到 视图函数的名称、参数,(注意不执行) 再执行process_view()方法

    (4)最后去执行视图函数

    玩法1(常规)

    from  django.utils.deprecation import MiddlewareMixin
    
    
    class M1(MiddlewareMixin):
        def process_request(self, request):
            print('M1.request') 
    
        def process_view(self, request,callback,callback_args,callback_kwargs ):
            print("M1.process_view")
         
        def process_response(self, request, response):
            print('M1.response')
            return response 
    
    
    
    class M2(MiddlewareMixin):
        def process_request(self, request):
            print('M2.request') 
    
        def process_view(self, request,callback,callback_args,callback_kwargs ):
            print("M2.process_view")
      
        def process_response(self, request, response):
            print('M2.response')
            return response
    View Code

    执行结果

    玩法2

    既然 process_view 拿到视图函数的名称、参数,(不执行) 再执行process_view()方法,最后才去执行视图函数!

    那可以在 执行process_view环节直接 把函数执行返回吗?

    from  django.utils.deprecation import MiddlewareMixin
    
    
    class M1(MiddlewareMixin):
        def process_request(self, request):
            print('M1.request')
                     # callback视图函数名称 callback_args,callback_kwargs 视图函数执行所需的参数
        def process_view(self, request,callback,callback_args,callback_kwargs ):
            print("M1.process_view")
            response=callback(request,*callback_args,**callback_kwargs)
            return response
        def process_response(self, request, response):
            print('M1.response')
            return response
    
    
    
    class M2(MiddlewareMixin):
        def process_request(self, request):
            print('M2.request')  
    
        def process_view(self, request,callback,callback_args,callback_kwargs ):
            print("M2.process_view")
        def process_response(self, request, response):
            print('M2.response')
            return response
    View Code

    执行结果

    结论:

    如果process_view函数有返回值,跳转到最后一个中间件, 执行最后一个中间件的response方法,逐步返回。

    和 process_request方法不一样哦!  request方法在当前中间件的response方法返回。

    2、process_exception(self, request, exception)方法

    from  django.utils.deprecation import MiddlewareMixin
    
    
    class M1(MiddlewareMixin):
        def process_request(self, request):
            print('M1.request')
            
        def process_view(self, request,callback,callback_args,callback_kwargs ):
            print("M1.process_view")
    
        def process_response(self, request, response):
            print('M1.response')
            return response
    
        def process_exception(self, request,exception):
            print('M1的process_exception')
    
    
    class M2(MiddlewareMixin):
        def process_request(self, request):
            print('M2.request') 
    
        def process_view(self, request,callback,callback_args,callback_kwargs ):
            print("M2.process_view")
    
        def process_response(self, request, response):
            print('M2.response')
            return response
    
        def process_exception(self, request, exception):
            print('M2的process_exception')
            
    View Code

    我去 加了process_exception方法 咋啥也没执行呢?!!原来是process_exception默认不执行!!!

     

    大爷的 原来process_exception方法在 视图函数执行出错的时候才会执行

    M1.request
    M2.request
    M1.process_view
    M2.process_view
    执行index
    M2的process_exception
    M1的process_exception
    Internal Server Error: /index/
    Traceback (most recent call last):
      File "C:UsersAdministratorAppDataLocalProgramsPythonPython36libsite-packagesdjangocorehandlersexception.py", line 41, in inner
        response = get_response(request)
      File "C:UsersAdministratorAppDataLocalProgramsPythonPython36libsite-packagesdjangocorehandlersase.py", line 187, in _get_response
        response = self.process_exception_by_middleware(e, request)
      File "C:UsersAdministratorAppDataLocalProgramsPythonPython36libsite-packagesdjangocorehandlersase.py", line 185, in _get_response
        response = wrapped_callback(request, *callback_args, **callback_kwargs)
      File "F:untitled1app01views.py", line 7, in index
        int("ok")
    ValueError: invalid literal for int() with base 10: 'ok'
    M2.response
    M1.response
    [03/Jul/2017 16:43:59] "GET /index/ HTTP/1.1" 500 62663
    View Code

    1、执行完所有 request 方法 

    2、执行 所有 process_view方法

    3、如果视图函数出错,执行process_exception(最终response,process_exception的return值)

     如果process_exception 方法有了 返回值 就不再执行 其他中间件的 process_exception,直接执行response方法响应 

    4.执行所有response方法

    5.最后返回process_exception的返回值

    M1.request
    M2.request
    M1.process_view
    M2.process_view
    执行index
    M2的process_exception (有了return值,直接执行response)
    M2.response
    M1.response

    process_exception的应用

    在视图函数执行出错时,返回错误信息。这样页面就不会 报错了!

    class M1(MiddlewareMixin):
        def process_request(self, request):
            print('M1.request')
    
        def process_view(self, request,callback,callback_args,callback_kwargs ):
            print("M1.process_view")
    
        def process_response(self, request, response):
            print('M1.response')
            return response
    
        def process_exception(self, request,exception):
            print('M1的process_exception')
    
    
    class M2(MiddlewareMixin):
        def process_request(self, request):
            print('M2.request')
    
        def process_view(self, request,callback,callback_args,callback_kwargs ):
            print("M2.process_view")
    
        def process_response(self, request, response):
            print('M2.response')
            return response
    
        def process_exception(self, request, exception):
            print('M2的process_exception')
            return HttpResponse('出错了兄弟!!!')
    View Code

    3、process_template_response()

    from  django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import HttpResponse
    
    class M1(MiddlewareMixin):
        def process_request(self, request):
            print('M1.request')
    
        def process_view(self, request,callback,callback_args,callback_kwargs ):
            print("M1.process_view")
    
        def process_response(self, request, response):
            print('M1.response')
            return response
    
    
        def process_exception(self, request,exception):
            print('M1的process_exception')
    
    
    class M2(MiddlewareMixin):
        def process_request(self, request):
            print('M2.request')
    
        def process_view(self, request,callback,callback_args,callback_kwargs ):
            print("M2.process_view")
    
        def process_response(self, request, response):
            print('M2.response')
            return response
    
        def process_exception(self, request, exception):
            print('M2的process_exception')
    
        def process_template_response(self,request,response):
            print('M2process_template_response')
            return response
    View Code

    process_template_response()默认不执行

     rocess_template_response()特性

     只有在视图函数的返回对象中有render方法才会执行!

    并把对象的render方法的返回值返回给用户(注意不返回视图函数的return的结果了,而是返回视图函数 return值(对象)的render方法

    from  django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import HttpResponse
    
    
    class M1(MiddlewareMixin):
        def process_request(self, request):
            print('M1.request')
    
        def process_view(self, request,callback,callback_args,callback_kwargs ):
            print("M1.process_view")
    
        def process_response(self, request, response):
            print('M1.response')
            return response
    
    
        def process_exception(self, request,exception):
            print('M1的process_exception')
    
    
    class M2(MiddlewareMixin):
        def process_request(self, request):
            print('M2.request')
    
        def process_view(self, request,callback,callback_args,callback_kwargs ):
            print("M2.process_view")
    
        def process_response(self, request, response):
            print('M2.response')
            return response
    
        def process_exception(self, request, exception):
            print('M2的process_exception')
    
        def process_template_response(self,request,response):  #如果视图函数中的返回值 中有render方法,才会执行 process_template_response
            print('M2process_template_response')
            return response
    View Code

    视图函数

    from django.shortcuts import render,HttpResponse
    
    # Create your views here.
    class Foo():
        def __init__(self,requ):
            self.req=requ
        def render(self):
            return HttpResponse('OKKKK')
    
    def index(request):
        print("执行index")
        obj=Foo(request)
        return obj
    View Code

    执行结果

     应用:

    既然process_template_respnse,不返回视图函数的return的结果,而是返回视图函数 return值(对象)的render方法;(多加了一个环节)

     就可以在 这个视图函数返回对象的 render方法里,做返回值的二次加工了!多加工几个,视图函数就可以随便使用了!

    (好比 喷雾器有了多个喷头,换不同的喷头喷出不同水,返回值就可以也组件化了)

    from django.shortcuts import render,HttpResponse
    
    # Create your views here.
    class Dict():   #对视图函数返回值做二次封装 !!
        def __init__(self,requ,msg):
            self.req=requ   
            self.msg=msg
        def render(self):
            a=self.msg #在render方法里面 把视图函数的 返回值 制作成字典 、列表等。。。 
                       #  如果新增了其他 一个视图函数直接,return对象 即可!不用每个视图函数都写 制作字典 列表 拼接的逻辑了
            return HttpResponse(a)    #
    
    def index(request):
        print("执行index")
        obj=Dict(request,"vv")
        return obj
    View Code

    中间件应用场景

    由于中间件工作在 视图函数执行前、执行后(像不像所有视图函数的装饰器!)适合所有的请求/一部分请求做批量处理

    1、做IP限制

    放在 中间件类的列表中,阻止某些IP访问了;

    2、URL访问过滤

    如果用户访问的是login视图(放过)

    如果访问其他视图(需要检测是不是有session已经有了放行,没有返回login),这样就省得在 多个视图函数上写装饰器了!

    3、缓存(还记得CDN吗?)

    客户端请求来了,中间件去缓存看看有没有数据,有直接返回给用户,没有再去逻辑层 执行视图函数

  • 相关阅读:
    Java异常处理和设计
    一次qps测试实践
    Alternate Task UVA
    Just Another Problem UVA
    Lattice Point or Not UVA
    Play with Floor and Ceil UVA
    Exploring Pyramids UVALive
    Cheerleaders UVA
    Triangle Counting UVA
    Square Numbers UVA
  • 原文地址:https://www.cnblogs.com/sss4/p/7106033.html
Copyright © 2020-2023  润新知