• 060.Python组件-中间件


    一 中间件基本介绍

    中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能。

    Django的中间件的定义:

    中间件是 Django 用来处理请求和响应的钩子框架。它是一个轻量级的、底层级的“插件”系统,用于全局性地控制Django 的输入或输出,可以理解为内置的app或者小框架。

    如果想修改请求,例如被传送到view中的HttpRequest对象。 或者你想修改view返回的HttpResponse对象,这些都可以通过中间件来实现。

    可能你还想在view执行之前做一些操作,这种情况就可以用 middleware来实现。

    Django默认的Middleware:

    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',
    ]

    MIDDLEWARE配置项是一个列表,列表中是一个个字符串,这些字符串其实是一个个类,也就是一个个中间件。cnfs也是一个中间件

    二 自建一个中间件

    2.1 process_request中间件

    root@darren-virtual-machine:~/PycharmProjects/cookie_seesion# vim cookie/Middlewares.py

    from django.utils.deprecation import MiddlewareMixin
    class MD1(MiddlewareMixin):
        def process_request(self,request):
            print("MD1下的process_request 方法")
    
    
    class MD2(MiddlewareMixin):
        def process_request(self, request):
            print("MD2下的process_request 方法")

    注册中间件

    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',
        'cookie.Middlewares.MD1',
        'cookie.Middlewares.MD2',
    ]

    访问http://127.0.0.1:8000/cookie/login/,调试结果如下

    MD1下的process_request 方法
    MD2下的process_request 方法

    这里的结果是按照注册顺序执行的

    配置views

    from django.shortcuts import render,redirect,HttpResponse
    
    # Create your views here.
    def login_required(func):
        def inner(request,*args,**kwargs):
            if not request.COOKIES.get("is_login"):
                return redirect("/cookie/login/")
            rep = func(request,*args,**kwargs)
            return rep
        return inner
    
    @login_required
    def index(request):
    #    if not request.COOKIES.get("is_login"):
    #        return redirect("/cookie/login/")
        print("index 视图")
        return render(request,"index.html")
    def login(request):
        if request.method == "GET":
            return  render(request,"login.html")
        else:
            username = request.POST.get("username")
            password = request.POST.get("password")
            if username == "joy" and password == "123456":
                rep = redirect("/cookie/index/")
                rep.set_cookie("is_login",True)
                return rep
            else:
                return redirect("/cookie/login/")
    def loginout(request):
        rep = redirect("/cookie/login/")
        rep.delete_cookie("is_login")
        return rep
    
    @login_required
    def order(request):
    #    if not request.COOKIES.get("is_login"):
    #        return redirect("/cookie/login/")
        return HttpResponse("oreder success")

    登录查看结果

    MD1下的process_request 方法
    MD2下的process_request 方法
    index 视图

    process_request是在view之后输出的

    2.2 process_reponse中间件

    root@darren-virtual-machine:~/PycharmProjects/cookie_seesion# vim cookie/Middlewares.py

    访问报错

    这是因为在request,必须有回应

    输出结果

    MD1下的process_request 方法
    MD2下的process_request 方法
    MD2下的process_reponse 方法
    MD1下的process_reponse 方法

    先执行response的MD2

    添加响应

    结果

    MD1下的process_request 方法
    MD2下的process_request 方法
    index 视图
    MD2下的process_reponse 方法
    MD1下的process_reponse 方法

    在return response返回的对象就是

    验证:

    views文件

    from django.shortcuts import render,redirect,HttpResponse
    
    # Create your views here.
    def login_required(func):
        def inner(request,*args,**kwargs):
            if not request.COOKIES.get("is_login"):
                return redirect("/cookie/login/")
            rep = func(request,*args,**kwargs)
            return rep
        return inner
    
    @login_required
    def index(request):
    #    if not request.COOKIES.get("is_login"):
    #        return redirect("/cookie/login/")
        print("index 视图")
        rep = render(request,"index.html")
        print(id(rep))
        return rep
    def login(request):
        if request.method == "GET":
            return  render(request,"login.html")
        else:
            username = request.POST.get("username")
            password = request.POST.get("password")
            if username == "joy" and password == "123456":
                rep = redirect("/cookie/index/")
                rep.set_cookie("is_login",True)
                return rep
            else:
                return redirect("/cookie/login/")
    def loginout(request):
        rep = redirect("/cookie/login/")
        rep.delete_cookie("is_login")
        return rep
    
    @login_required
    def order(request):
    #    if not request.COOKIES.get("is_login"):
    #        return redirect("/cookie/login/")
        return HttpResponse("oreder success")

    中间件

    root@darren-virtual-machine:~/PycharmProjects/cookie_seesion# vim cookie/Middlewares.py

    from django.utils.deprecation import MiddlewareMixin
    class MD1(MiddlewareMixin):
        def process_request(self,request):
            print("MD1下的process_request 方法")
        def process_response(self,request,response):
            print("MD1下的process_reponse 方法")
            print(id(response))
            return response
    
    class MD2(MiddlewareMixin):
        def process_request(self, request):
            print("MD2下的process_request 方法")
        def process_response(self,request,response):
            print("MD2下的process_reponse 方法")
            return response

    访问结果,是一致的

    MD1下的process_request 方法
    MD2下的process_request 方法
    index 视图
    139857132829104
    MD2下的process_reponse 方法
    MD1下的process_reponse 方法
    139857132829104

    所以上面错误的原因,是因为resonse没有返回值,则默认的返回值为null,导致报错,返回response后,就是返回render(request,"index.html")

    在request添加返回值

    root@darren-virtual-machine:~/PycharmProjects/cookie_seesion# vim cookie/Middlewares.py

    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import render,redirect,HttpResponse
    class MD1(MiddlewareMixin):
        def process_request(self,request):
            print("MD1下的process_request 方法")
            return HttpResponse("Hello  我来了")
        def process_response(self,request,response):
            print("MD1下的process_response 方法")
            print(id(response))
            return response
    
    class MD2(MiddlewareMixin):
        def process_request(self, request):
            print("MD2下的process_request 方法")
        def process_response(self,request,response):
            print("MD2下的process_response 方法")
            return response

    访问http://127.0.0.1:8000/cookie/login/,没有到view层

    输出

    MD1下的process_request 方法
    MD1下的process_response 方法
    140023033668160

    如图,当reques的中间件中,有返回值,就会直接返回,不会走到下面的reques和视图层,生命请求周期如下:

    2.3 process_view方法

    该方法有四个参数

    • request是HttpRequest对象。
    • view_func是Django即将使用的视图函数。 (它是实际的函数对象,而不是函数的名称作为字符串。)
    • view_args是将传递给视图的位置参数的列表.
    • view_kwargs是将传递给视图的关键字参数的字典。 view_args和view_kwargs都不包含第一个视图参数(request)。

      Django会在调用视图函数之前调用process_view方法。

      它应该返回None或一个HttpResponse对象。 如果返回None,Django将继续处理这个请求,执行任何其他中间件的process_view方法,然后在执行相应的视图。 如果它返回一个HttpResponse对象,Django不会调用适当的视图函数。 它将执行中间件的process_response方法并将应用到该HttpResponse并返回结果。

    添加process_view

    root@darren-virtual-machine:~/PycharmProjects/cookie_seesion# vim cookie/Middlewares.py

    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import render,redirect,HttpResponse
    class MD1(MiddlewareMixin):
        def process_request(self,request):
            print("MD1下的process_request 方法")
            #return HttpResponse("Hello  我来了")
        def process_response(self,request,response):
            print("MD1下的process_response 方法")
            #print(id(response))
            return response
    
        def process_view(self,request,view_func,view_args,view_kwargs):
            print("MD1下的process_view 方法")
    
    class MD2(MiddlewareMixin):
        def process_request(self, request):
            print("MD2下的process_request 方法")
        def process_response(self,request,response):
            print("MD2下的process_response 方法")
            return response
    
        def process_view(self,request,view_func,view_args,view_kwargs):
            print("MD2下的process_view 方法")

    输出结果

    MD1下的process_request 方法
    MD2下的process_request 方法
    MD1下的process_view 方法
    MD2下的process_view 方法
    index 视图
    MD2下的process_response 方法
    MD1下的process_response 方法

    process_view方法是在process_request之后,视图函数之前执行的,执行顺序按照MIDDLEWARE中的注册顺序从前到后顺序执行。

      

     在MD1下的porcess_view返回一个返回值

    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import render,redirect,HttpResponse
    class MD1(MiddlewareMixin):
        def process_request(self,request):
            print("MD1下的process_request 方法")
            #return HttpResponse("Hello  我来了")
        def process_response(self,request,response):
            print("MD1下的process_response 方法")
            #print(id(response))
            return response
    
        def process_view(self,request,view_func,view_args,view_kwargs):
            print("MD1下的process_view 方法")
            return view_func(request)
    class MD2(MiddlewareMixin):
        def process_request(self, request):
            print("MD2下的process_request 方法")
        def process_response(self,request,response):
            print("MD2下的process_response 方法")
            return response
    
        def process_view(self,request,view_func,view_args,view_kwargs):
            print("MD2下的process_view 方法")

    执行结果

    MD1下的process_request 方法
    MD2下的process_request 方法
    MD1下的process_view 方法
    index 视图
    MD2下的process_response 方法
    MD1下的process_response 方法

    2.4 process_exception

    语法:

    process_exception(self, request, exception)

    该方法两个参数:

    • HttpRequest对象
    • exception是视图函数异常产生的Exception对象。

      这个方法只有在视图函数中出现异常了才执行,它返回的值可以是一个None也可以是一个HttpResponse对象。如果是HttpResponse对象,Django将调用模板和中间件中的process_response方法,并返回给浏览器,否则将默认处理异常。如果返回一个None,则交给下一个中间件的process_exception方法来处理异常。它的执行顺序也是按照中间件注册顺序的倒序执行。

    添加process_exception

    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import render,redirect,HttpResponse
    class MD1(MiddlewareMixin):
        def process_request(self,request):
            print("MD1下的process_request 方法")
            #return HttpResponse("Hello  我来了")
            
        def process_response(self,request,response):
            print("MD1下的process_response 方法")
            #print(id(response))
            return response
    
        def process_view(self,request,view_func,view_args,view_kwargs):
            print("MD1下的process_view 方法")
            #return view_func(request)
    
        def process_exception(self,request,exception):
            print("MD1下的process_exception 方法")
            
    class MD2(MiddlewareMixin):
        def process_request(self, request):
            print("MD2下的process_request 方法")
            
        def process_response(self,request,response):
            print("MD2下的process_response 方法")
            return response
    
        def process_view(self,request,view_func,view_args,view_kwargs):
            print("MD2下的process_view 方法")
            
        def process_expection(self,request,exception):
            print("MD2下的process_exception 方法")

    访问结果

    MD1下的process_request 方法
    MD2下的process_request 方法
    MD1下的process_view 方法
    MD2下的process_view 方法
    index 视图
    MD2下的process_response 方法
    MD1下的process_response 方法

    并没有exception,是因为需要view异常才会触发

    制造views异常

    from django.shortcuts import render,redirect,HttpResponse
    
    # Create your views here.
    def login_required(func):
        def inner(request,*args,**kwargs):
            if not request.COOKIES.get("is_login"):
                return redirect("/cookie/login/")
            rep = func(request,*args,**kwargs)
            return rep
        return inner
    
    @login_required
    def index(request):
    #    if not request.COOKIES.get("is_login"):
    #        return redirect("/cookie/login/")
        print("index 视图")
        int("aaa")
        rep = render(request,"index.html")
        #print(id(rep))
        return rep
    def login(request):
        if request.method == "GET":
            return  render(request,"login.html")
        else:
            username = request.POST.get("username")
            password = request.POST.get("password")
            if username == "joy" and password == "123456":
                rep = redirect("/cookie/index/")
                rep.set_cookie("is_login",True)
                return rep
            else:
                return redirect("/cookie/login/")
    def loginout(request):
        rep = redirect("/cookie/login/")
        rep.delete_cookie("is_login")
        return rep
    
    @login_required
    def order(request):
    #    if not request.COOKIES.get("is_login"):
    #        return redirect("/cookie/login/")
        return HttpResponse("oreder success")

    访问http://127.0.0.1:8000/cookie/index/

     输出结果

    MD1下的process_request 方法
    MD2下的process_request 方法
    MD1下的process_view 方法
    MD2下的process_view 方法
    index 视图
    MD2下的process_exception 方法
    MD1下的process_exception 方法
    MD2下的process_response 方法
    MD1下的process_response 方法 

    在exception添加错误返回

    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import render,redirect,HttpResponse
    class MD1(MiddlewareMixin):
        def process_request(self,request):
            print("MD1下的process_request 方法")
            #return HttpResponse("Hello  我来了")
    
        def process_response(self,request,response):
            print("MD1下的process_response 方法")
            #print(id(response))
            return response
    
        def process_view(self,request,view_func,view_args,view_kwargs):
            print("MD1下的process_view 方法")
            #return view_func(request)
    
        def process_exception(self,request,exception):
            print("MD1下的process_exception 方法")
            return HttpResponse(exception)
    
    class MD2(MiddlewareMixin):
        def process_request(self, request):
            print("MD2下的process_request 方法")
    
        def process_response(self,request,response):
            print("MD2下的process_response 方法")
            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 方法")

    访问结果没有报错

    输出

    MD1下的process_request 方法
    MD2下的process_request 方法
    MD1下的process_view 方法
    MD2下的process_view 方法
    index 视图
    MD2下的process_exception 方法
    MD1下的process_exception 方法
    MD2下的process_response 方法
    MD1下的process_response 方法

    在MD2返回

    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import render,redirect,HttpResponse
    class MD1(MiddlewareMixin):
        def process_request(self,request):
            print("MD1下的process_request 方法")
            #return HttpResponse("Hello  我来了")
    
        def process_response(self,request,response):
            print("MD1下的process_response 方法")
            #print(id(response))
            return response
    
        def process_view(self,request,view_func,view_args,view_kwargs):
            print("MD1下的process_view 方法")
            #return view_func(request)
    
        def process_exception(self,request,exception):
            print("MD1下的process_exception 方法")
    
    
    class MD2(MiddlewareMixin):
        def process_request(self, request):
            print("MD2下的process_request 方法")
    
        def process_response(self,request,response):
            print("MD2下的process_response 方法")
            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 方法")
            return HttpResponse(exception)

    访问结果

    MD1下的process_request 方法
    MD2下的process_request 方法
    MD1下的process_view 方法
    MD2下的process_view 方法
    index 视图
    MD2下的process_exception 方法
    MD2下的process_response 方法
    MD1下的process_response 方法

    没有MD1的exception,已经跳过,流程如下

    绿色为正常流程,红色是则MD2添加return返回

  • 相关阅读:
    团队作业2 需求分析与原型设计
    团队作业1
    获取公众号关注二维码url
    用户绑定公众号列表与未绑定公众号列表
    修改个人信息
    公众号登录
    idea去掉右侧小窗口代码块预览,idea去掉右侧代码预览
    微信退款 订单金额或退款金额与之前请求不一致,请核实后再试
    取消支付
    linux命令发送请求
  • 原文地址:https://www.cnblogs.com/zyxnhr/p/12669411.html
Copyright © 2020-2023  润新知