博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
day62 中间件
阅读量:5279 次
发布时间:2019-06-14

本文共 12667 字,大约阅读时间需要 42 分钟。

一.中间件的介绍 

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

 

  1. Django 的请求生命周期

 

  2.Django默认自带的一些中间件

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

   3.执行中间件的过程

 

 二. 自定义中间件

  1.在项目中创建一个包

  在项目中创建一个包,随便起名字,一般都放在一个叫做utils的包里面, 表示一个公用的组件,创建一个py文件,随便起名字, 例如叫做:middlewares.py,内容如下

 

from django.utils.deprecation import MiddlewareMixinclass MD1(MiddlewareMixin):    #自定义中间件,不是必须要有下面这两个方法,有request方法说明请求来了要处理, 有response方法说明响应出去时需要处理,不是非要写这两个方法,如果你没写process_response方法, 那么会一层一层的往上找,哪个中间件有process_response方法就将返回对象给哪个中间件    def process_request(self, request):        print("MD1里面的 process_request")    def process_response(self, request, response):        print("MD1里面的 process_response")        return response

 

  2.在 settings.py 文件中进行注册

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',    'utils.middlewares.MD1',  # 自定义中间件MD1,这个写的是你项目路径下的一个路径,                 例如,如果你放在项目下,文件夹名成为utils,                 那么这里应该写utils.middlewares.MD1    'utils.middlewares.MD2'  # 自定义中间件MD2]

 

三.常用方法

  1. process_request 

process_request有一个参数,就是request,这个request和     视图函数中的request是一样的。它的返回值可以是None也可以是HttpResponse对象。返回值是None的话,     按正常流程继续走,交给下一个中间件处理,如果是HttpResponse对象,     Django将不执行视图函数,而将相应对象返回给浏览器。

 

from django.utils.deprecation import MiddlewareMixinclass MD1(MiddlewareMixin):    def process_request(self, request):        print("MD1里面的 process_request")class MD2(MiddlewareMixin):    def process_request(self, request):        print("MD2里面的 process_request")        pass

  ①在注册时 先注册 MD1 再注册 MD2,打印结果为:

MD1里面的 process_requestMD2里面的 process_requestapp01 中的 index视图

  ②在注册时 先注册MD2 再注册 MD1,打印结果为:

MD2里面的 process_requestMD1里面的 process_requestapp01 中的 index视图
注:   多个中间件中的process_response方法是按照MIDDLEWARE中的注册顺序倒序执行的, 也就是说第一个中间件的process_request方法首先执行,而它的process_response 方法最后执行,最后一个中间件的process_request方法最后一个执行, 它的process_response方法是最先执行。

 

  2. process_response

  它有两个参数,一个是request,一个是response,request就是上述例子中一样的对象, response是视图函数返回的HttpResponse对象。该方法的返回值也必须是HttpResponse对象。

  ①示例1:

from django.utils.deprecation import MiddlewareMixinclass MD1(MiddlewareMixin):    def process_request(self, request):        print("MD1里面的 process_request")        #不必须写return值    def process_response(self, request, response):#request和response两个参数必须有,名字随便取        print("MD1里面的 process_response")        #print(response.__dict__['_container'][0].decode('utf-8')) #查看响应体里面的内容的方法     return response  #必须有返回值,写return response  ,这个response就像一个接力棒一样        #return HttpResponse('瞎搞') ,如果你写了这个,那么你视图返回过来的内容就被它给替代了class MD2(MiddlewareMixin):    def process_request(self, request):        print("MD2里面的 process_request")        pass    def process_response(self, request, response): #request和response两个参数必须要有,名字随便取        print("MD2里面的 process_response")         return response  #必须返回response,不然你上层的中间件就没有拿到httpresponse对象,就会报错

  结果:

MD2里面的 process_requestMD1里面的 process_requestapp01 中的 index视图MD1里面的 process_responseMD2里面的 process_response
看结果可知:      process_response方法是在视图函数之后执行的,并且顺序是MD1比MD2先执行。 (此时settings.py中 MD2比MD1先注册)      多个中间件中的process_response方法是按照MIDDLEWARE中的注册顺序倒序执行的, 也就是说第一个中间件的process_request方法首先执行,而它的process_response方法最后执行, 最后一个中间件的process_request方法最后一个执行,它的process_response方法是最先执行。

  ②示例2:

from django.utils.deprecation import MiddlewareMixinfrom django.shortcuts import HttpResponseclass Md1(MiddlewareMixin):    def process_request(self,request):        print("Md1请求")      return HttpResponse("Md2中断")
     #process_request方法里面不写返回值,默认也是返回None,如果你自己写了return None,       也是一样的效果,不会中断你的请求,但是如果你return 的一个httpresponse对象,       那么就会在这个方法中断你的请求,直接返回给用户,这就成了非正常的流程了         #并且,如果你在这里return了httpresponse对象,那么会从你这个中间件类中的       process_response方法开始执行返回操作,所以这个类里面只要有process_response方法,       肯定会执行     def process_response(self,request,response):        print("Md1返回")        return responseclass Md2(MiddlewareMixin):    def process_request(self,request):        print("Md2请求")            def process_response(self,request,response):        print("Md2返回")        return response

  结果为:

Md1请求Md1返回

  流程图如下:

 

     实例: 访问白名单设置

class M1(MiddlewareMixin):    def process_request(self,request):        #设置路径白名单,只要访问的是login登陆路径,就不做这个cookie认证        if request.path not in [reverse('login'),]:            print('我是M1中间件') #客户端IP地址            # return HttpResponse('sorry,没有通过我的M1中间件')            is_login = request.COOKIES.get('is_login', False)            if is_login:                pass            else:                # return render(request,'login.html')                return redirect(reverse('login'))        else:            return None #别忘了return None    def process_response(self,request,response):        print('M1响应部分')        # print(response.__dict__['_container'][0].decode('utf-8'))        return response        # return HttpResponse('瞎搞')

 

  3. process_view

 

process_view(self, request, view_func, view_args, view_kwargs)      该方法有四个参数      request是HttpRequest对象。      view_func是Django即将使用的视图函数。 (             它是实际的函数对象,而不是函数的名称作为字符串。)      view_args是将传递给视图的位置参数的列表.      view_kwargs是将传递给视图的关键字参数的字典。             view_args和view_kwargs都不包含第一个视图参数(request)。      Django会在调用视图函数之前,路由匹配之后(process_request方法之后)调用process_view方法。

 

  ① 流程图

 

   ② 示例:(访问index视图函数)

from django.utils.deprecation import MiddlewareMixinclass MD1(MiddlewareMixin):    def process_request(self, request):        print("MD1里面的 process_request")    def process_response(self, request, response):        print("MD1里面的 process_response")        return response    def process_view(self, request, view_func, view_args, view_kwargs):        print("-" * 80)        print("MD1 中的process_view")        print(view_func, view_func.__name__) #就是url映射到的那个视图函数,           也就是说每个中间件的这个process_view已经提前拿到了要执行的那个视图函数         #ret = view_func(request) #提前执行视图函数,不用到了上图的试图函数的位置再执行,           如果你视图函数有参数的话,可以这么写 view_func(request,view_args,view_kwargs)         #return ret  #直接就在MD1中间件这里这个类的process_response给返回了,             就不会去找到视图函数里面的这个函数去执行了。class MD2(MiddlewareMixin):    def process_request(self, request):        print("MD2里面的 process_request")        pass    def process_response(self, request, response):        print("MD2里面的 process_response")        return response    def process_view(self, request, view_func, view_args, view_kwargs):        print("-" * 80)        print("MD2 中的process_view")        print(view_func, view_func.__name__)

  结果:

MD1里面的 process_requestMD2里面的 process_request--------------------------------------------------------------------------------MD1 中的process_view
index--------------------------------------------------------------------------------MD2 中的process_view
indexapp01 中的 index视图MD2里面的 process_responseMD1里面的 process_response

  ③写了返回对象的情况

 

 

返回值是HttpResponse:            当前中间件之后的中间的process_view方法和视图函数都不执行,直接执行最后一个中间件的process_reponse方法.

 

 

 

  4.process_exception

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

 

   ①示例1:

from django.utils.deprecation import MiddlewareMixinclass MD1(MiddlewareMixin):    def process_request(self, request):        print("MD1里面的 process_request")    def process_response(self, request, response):        print("MD1里面的 process_response")        return response    def process_view(self, request, view_func, view_args, view_kwargs):        print("-" * 80)        print("MD1 中的process_view")        print(view_func, view_func.__name__)    def process_exception(self, request, exception):        print(exception)        print("MD1 中的process_exception")class MD2(MiddlewareMixin):    def process_request(self, request):        print("MD2里面的 process_request")        pass    def process_response(self, request, response):        print("MD2里面的 process_response")        return response    def process_view(self, request, view_func, view_args, view_kwargs):        print("-" * 80)        print("MD2 中的process_view")        print(view_func, view_func.__name__)    def process_exception(self, request, exception):        print(exception)        print("MD2 中的process_exception")

  在视图函数中抛出一个异常

def index(request):    print("app01 中的 index视图")    raise ValueError("呵呵")    return HttpResponse("O98K")

  流程图:

 

 

   ②示例2:在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("-" * 80)        print("MD2 中的process_view")        print(view_func, view_func.__name__)    def process_exception(self, request, exception):        print(exception)        print("MD2 中的process_exception")        return HttpResponse(str(exception))  # 返回一个响应对象

 

   结果:

 

MD1里面的 process_requestMD2里面的 process_request--------------------------------------------------------------------------------MD1 中的process_view
index--------------------------------------------------------------------------------MD2 中的process_view
indexapp01 中的 index视图呵呵MD2 中的process_exceptionMD2里面的 process_responseMD1里面的 process_response

  流程图:

 

返回None:        正常流程.返回HttpResponse对象:    后面的中间件的process_view方法不执行,直接执行最后一个中间件的process_response方法.

 

process_template_response(用的比较少)

process_template_response(self, request, response)

它的参数,一个HttpRequest对象,response是TemplateResponse对象(由视图函数或者中间件产生)。

process_template_response是在视图函数执行完成后立即执行,但是它有一个前提条件,那就是视图函数返回的对象有一个render()方法(或者表明该对象是一个TemplateResponse对象或等价方法)。

class MD1(MiddlewareMixin):    def process_request(self, request):        print("MD1里面的 process_request")    def process_response(self, request, response):        print("MD1里面的 process_response")        return response    def process_view(self, request, view_func, view_args, view_kwargs):        print("-" * 80)        print("MD1 中的process_view")        print(view_func, view_func.__name__)    def process_exception(self, request, exception):        print(exception)        print("MD1 中的process_exception")        return HttpResponse(str(exception))    def process_template_response(self, request, response):        print("MD1 中的process_template_response")        return responseclass 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("-" * 80)        print("MD2 中的process_view")        print(view_func, view_func.__name__)    def process_exception(self, request, exception):        print(exception)        print("MD2 中的process_exception")    def process_template_response(self, request, response):        print("MD2 中的process_template_response")        return response

views.py中:

def index(request):    print("app01 中的 index视图")    def render():        print("in index/render")        return HttpResponse("O98K")    rep = HttpResponse("OK")    rep.render = render    return rep

访问index视图,终端输出的结果:

MD2里面的 process_requestMD1里面的 process_request--------------------------------------------------------------------------------MD2 中的process_view
index--------------------------------------------------------------------------------MD1 中的process_view
indexapp01 中的 index视图MD1 中的process_template_responseMD2 中的process_template_responsein index/renderMD1里面的 process_responseMD2里面的 process_response

从结果看出:

视图函数执行完之后,立即执行了中间件的process_template_response方法,顺序是倒序,先执行MD1的,在执行MD2的,接着执行了视图函数返回的HttpResponse对象的render方法,返回了一个新的HttpResponse对象,接着执行中间件的process_response方法。

 

 

 补充:  登录时浏览器自动加  "/"

  ①在输入时

 

   ②浏览器自动加 '/'

 

 

   ③在一些情况下不需要加时,

在settings.py文件中进行设置

 

 

转载于:https://www.cnblogs.com/lw1095950124/p/10499985.html

你可能感兴趣的文章
PHP的配置
查看>>
Struts框架----进度1
查看>>
Round B APAC Test 2017
查看>>
MySQL 字符编码问题详细解释
查看>>
寄Android开发Gradle你需要知道的知识
查看>>
css & input type & search icon
查看>>
C# 强制关闭当前程序进程(完全Kill掉不留痕迹)
查看>>
语音识别中的MFCC的提取原理和MATLAB实现
查看>>
0320-学习进度条
查看>>
MetaWeblog API Test
查看>>
移动、尺寸改变
查看>>
c# 文件笔记
查看>>
类和结构
查看>>
心得25--JDK新特性9-泛型1-加深介绍
查看>>
安装NVIDIA驱动时禁用自带nouveau驱动
查看>>
HDU-1255 覆盖的面积 (扫描线)
查看>>
Java 中 静态方法与非静态方法的区别
查看>>
Jenkins+ProGet+Windows Batch搭建全自动的内部包(NuGet)打包和推送及管理平台
查看>>
线程池的概念
查看>>
Java 序列化
查看>>