• django8-django的中间件


    1.django的客户请求流程

      之前登录功能 ,需要获取用户的sesssion ,但是每个视图函数都要加装饰器来校验很不合理 ,中间件就可以解决这个问题 

      用户客户端--->wsgi(封装了request对象)--->中间件(框架hook)--->路由--->views--->models--->db--->template---中间件--->wsgi--->客户端

    2.什么是中间件

      django中间件用来处理django的请求和响应框架级别的钩子 ,在全局范围内改变django的输入和输出 ,有多种类型中间件, 每个中间件都可以完成特定功能 ,可以帮助我们在执行视图函数前后完成额外操作 ,本质是类

      settings中MIDDLEWARE配置的就是中间件信息 ,字符串也是一个个类 ,也就是一个个中间件 ,可以通过import点击查看类

    3.自定义中间件

      5种中间件 ,关注点在于 参数! 执行的时机! 执行顺序! 返回值! 

      本质就是类 ,类中定义下前面的五种方法 ,在不同时机执行产生不同作用!

      process_request(self,request)

      process_view(self,request,view_func,view_args,view_kwargs)

      process_template_response(self,request,response)

      process_exception(self,request,exception)

      process_response(self,request,response)

      

      1)process_request(self,request)

        参数: wsgi返回的request对象

        执行时间: 在收到request后执行之前 (截断不满足要求的请求)

        执行顺序: 按照setting注册顺序执行 ,在注册的类中按顺序拿出每个类中这个方法执行

        返回值: 

          当返回值为空None: url-->views

          当返回response对象: 直接返回客户端 

    ##middle/middles.py 一个类就是一个中间件 ,可以写多个
    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import render, HttpResponse
    
    class MD1(MiddlewareMixin):
        def process_request(self, request):
            print('MD1 process_request')
            # return HttpResponse('拒绝访问')    #如果return那么就会直接返回客户端
    
    ##settings.py注册
    MIDDLEWARE = [
    ...
        'middle.middles.MD1',
    ...
    ]

      2)process_response(self,request,response)

        参数: wsgi返回的request对象 ,response对象(可能是视图函数返回的 ,也可能是process_request返回的)

        执行时机: 在视图函数执行之后 ,还可能是是process_request有返回值之后按顺序执行

        执行顺序: 按照setting注册顺序倒序执行 ,在注册的类中倒叙获取每个类中的process_response方法执行

        返回值: 必须返回response对象

    ##/middle/middles.py  写两个中间件查看执行顺序
    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import render, HttpResponse
    
    class MD1(MiddlewareMixin):
        def process_request(self, request):
            print('MD1 process_request')
            # return HttpResponse('拒绝访问')
    
        def process_response(self, request, response):
            print('MD1 process_response')
            # return HttpResponse('拒绝访问')
            return response
    
    class MD2(MiddlewareMixin):
        def process_request(self, request):
            print('MD2 process_request')
            # return HttpResponse('拒绝访问')
    
        def process_response(self, request, response):
            print('MD2 process_response')
            # return HttpResponse('拒绝访问')
            return response
    
    ##settings 注册两个中间件类
    MIDDLEWARE = [
    ...
        'middle.middles.MD1',
        'middle.middles.MD2',
    ...
    ]

      3)process_view(self,request,view_func ,view_args, view_kwargs)

        参数: wsgi给的request对象 ,view_func匹配本次执行视图函数 ,view_args匹配本次视图函数位置参数 ,view_kwargs匹配本次视图函数关键字参数

        执行时机: 在url匹配到视图函数后执行 ,再执行视图函数

        执行顺序: 按照setting注册顺序执行

        返回值: 

          返回值为空: 正常流程(process_request--->url--->process_view--->views.py--->process_response)

          response对象: 截断流程(process_request--->url--->process_view(直接跳过所有view方法,和所有视图函数直接返回response)-->process_response)

    ##middle/middles.py 有返回值的view ,观察执行结果
    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import render, HttpResponse
    
    class MD1(MiddlewareMixin):
        def process_request(self, request):
            print('MD1 process_request')
            # return HttpResponse('拒绝访问')
    
        def process_response(self, request, response):
            print('MD1 process_response')
            # return HttpResponse('拒绝访问')
            return response
    
        def process_view(self, request, view_func, view_args, view_kwargs):
            print('MD1 process_view', view_func)
            return HttpResponse('test')
    
    class MD2(MiddlewareMixin):
        def process_request(self, request):
            print('MD2 process_request')
            # return HttpResponse('拒绝访问')
    
        def process_response(self, request, response):
            print('MD2 process_response')
            # return HttpResponse('拒绝访问')
            return response
    
        def process_view(self, request, view_func, view_args, view_kwargs):
            print('MD2 process_view', view_func)
    
    
    ###执行结果
    MD1 process_request
    MD2 process_request
    MD1 process_view <function presslist at 0x0408BF60>        #MD1有return ,MD2的view就不执行了直接跳到response
    MD2 process_response
    MD1 process_response

      4)process_exception(self ,request, exception)

        参数: wsgi返回的request对象 ,exception视图函数的异常

        执行时机: 在执行视图函数 ,有异常的情况

        执行顺序: 按setting的注册倒序执行 

        返回值: 

          返回值为空: 交给下一个process_exception处理

          返回response对象: 跳过其他process_exception ,开始process_response的倒叙顺序执行  (如果所有的exception都没处理这个异常 ,那么最后会由django做异常处理)

    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import render, HttpResponse
    
    
    class MD1(MiddlewareMixin):
        def process_request(self, request):
            print('MD1 process_request')
            # return HttpResponse('拒绝访问')
    
        def process_response(self, request, response):
            print('MD1 process_response')
            # return HttpResponse('拒绝访问')
            return response
    
        def process_view(self, request, view_func, view_args, view_kwargs):
            print('MD1 process_view', view_func)
    
        def process_exception(self, request, exception):
            print('MD1 process_exception')
            print(exception)
            return HttpResponse(exception)
    
    
    class MD2(MiddlewareMixin):
        def process_request(self, request):
            print('MD2 process_request')
            # return HttpResponse('拒绝访问')
    
        def process_response(self, request, response):
            print('MD2 process_response')
            # return HttpResponse('拒绝访问')
            return response
    
        def process_view(self, request, view_func, view_args, view_kwargs):
            print('MD2 process_view')
    
        def process_exception(self, request, exception):
            print('MD2 process_exception')
            print(exception)

    ###视图函数中加入一条错误 ,让process_exception捕获 ,

    MD1 process_request
    MD2 process_request
    MD1 process_view <function presslist at 0x03BAC078>
    MD2 process_view
    MD2 process_exception
    invalid literal for int() with base 10: 'ok'
    MD1 process_exception
    invalid literal for int() with base 10: 'ok'
    MD2 process_response
    MD1 process_response

      5)process_template_response(self,request,response)

        参数: wsgi返回的request对象

        执行时机: 视图函数执行返回Templateresponse对象才会执行

        执行顺序: 根据setting注册顺序倒序执行 ,如果设置了多个该类型中间件结果会是最后一个

        返回值: response对象(Templateresponse对象)

        Templateresponse对象: 这个对象使用与render相似 ,但是render最终返回的也是Httpresponse对象 ! 目前两个对象区别就在于templateresponse可以在中间件进行修改

    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import render, HttpResponse
    
    
    class MD1(MiddlewareMixin):
        def process_request(self, request):
            print('MD1 process_request')
            # return HttpResponse('拒绝访问')
    
        def process_response(self, request, response):
            print('MD1 process_response')
            # return HttpResponse('拒绝访问')
            return response
    
        def process_view(self, request, view_func, view_args, view_kwargs):
            print('MD1 process_view', view_func)
    
        def process_exception(self, request, exception):
            print('MD1 process_exception')
            print(exception)
            return HttpResponse(exception)
    
        def process_template_response(self, request, response):
            response.context_data = {'author': 'ggg'}
            print('MD1 process_template_response')
            return response
    
    
    ##middle/middles.py 指定templateresponse返回的数据
    class MD2(MiddlewareMixin):
        def process_request(self, request):
            print('MD2 process_request')
            # return HttpResponse('拒绝访问')
    
        def process_response(self, request, response):
            print('MD2 process_response')
            # return HttpResponse('拒绝访问')
            return response
    
        def process_view(self, request, view_func, view_args, view_kwargs):
            print('MD2 process_view')
    
        def process_exception(self, request, exception):
            print('MD2 process_exception')
            print(exception)
    
        def process_template_response(self, request, response):
            response.context_data = {'author': '7777'}
            print('MD2 process_template_response')
            return response
    
    ##视图函数返回编程templateresponse对象
    from django.template.response import TemplateResponse
    
    def presslist(request):
        msg_all = models.presslist.objects.all()
        return TemplateResponse(request, 'cbs.html', {'msg': msg_all, 'author': 'qgw'})

    5.session使用中间件优化

      将校验的session的过程放到process_request中

        1.如果客户端没有cookie存储的sessionid则跳转到login函数

        2.如果用户访问login函数那么就不需要cookie

    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import render, HttpResponse, reverse, redirect, HttpResponseRedirect
    
    
    class MD1(MiddlewareMixin):
        """缺陷是如果login函数能跳过中间件就好了"""
        def process_request(self, request):
            if not request.session.get('auth') and request.path_info != reverse('tlogin'):
                nowurl = request.path_info
                url = reverse('tlogin') + '?next={}'.format(nowurl)
                if nowurl == reverse('tlogin'):
                    url = reverse('tlogin')
                return redirect(url)

    解析csrf安全的中间件

  • 相关阅读:
    CF687D Dividing Kingdom II
    图论——EK算法
    P6082 [JSOI2015]salesman
    联合权值——树上问题2014noip
    P2071 座位安排——二分图最大匹配
    匈牙利优化时间戳的正确性
    P1541 乌龟棋——线性动规
    P1858 多人背包
    P3558 [POI2013]BAJ-Bytecomputer——线性动归
    P2303 [SDOI2012] Longge 的问题
  • 原文地址:https://www.cnblogs.com/quguanwen/p/11420975.html
Copyright © 2020-2023  润新知