django -- 中间件

django -- 中间件,第1张

概述前戏 在前面我们给index和home页面通过加装饰器的方法来判断是不是登录过,如果没登录就返回登录页面。想想也没有什么问题,但是如果我们的视图函数有几百个呢?难道要给这几百个视图函数都加上装饰器吗?答案当然是否定的。我们可以通过中间件的方式来实现。 什么是中间件 看下官方是怎么解释的:中间件是一个用来处理Django的请求和响应的框架级别的钩子。它是一个轻量、低级别的插件系统,用于在全局范围内改 前戏

在前面我们给index和home页面通过加装饰器的方法来判断是不是登录过,如果没登录就返回登录页面。想想也没有什么问题,但是如果我们的视图函数有几百个呢?难道要给这几百个视图函数都加上装饰器吗?答案当然是否定的。我们可以通过中间件的方式来实现。

什么是中间件

看下官方是怎么解释的:中间件是一个用来处理Django的请求和响应的框架级别的钩子。它是一个轻量、低级别的插件系统,用于在全局范围内改变Django的输入和输出。每个中间件组件都负责做一些特定的功能。

用大白话说就是在视图函数执行之前和执行之后可以做一些额外的 *** 作,本质上就是一个自定义类,类中定义了几个方法,Django会在处理请求的特定时间去执行这些方法。

注意:因为中间件影响的是全局,所以需要谨慎使用,使用不当会影响性能。

其实我们一直在使用中间件,来看下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,]

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

自定义中间件

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

process_request(self,request) process_vIEw(self,request,vIEw_func,vIEw_args,vIEw_kwargs) process_template_response(self,response) process_exception(self,exception) process_response(self,response)

以上方法的返回值可以是一个None或一个httpResponse对象,如果是None,则继续按照Django定义的规则向后继续执行,如果是httpResponse对象,则直接将该对象返回给用户,就不执行视图里的函数了

process_request

process_request有一个参数,就是request,这个request和视图函数中的request是一样的,可以使用ID(request)查看一下。

我们先来写一个中间件,在app下创建个py文件,里面写如下代码

from django.utils.deprecation import MIDdlewareMixinclass MIDdle1(MIDdlewareMixin):  # 需要继承这个类    def process_request(self,request):        print(ID(request))        print(这是中间件1中的process_request方法)

这就是我们自定义的中间件了,写好之后,需要在settings.py里的MIDDLEWARE里注册

MIDDLEWARE = [    django.mIDdleware.security.SecurityMIDdleware,    appTest01.mymIDdleware.MIDdle1,# 自定义的中间件]

然后我们去在视图函数里写个视图,如下

def test(request):    print(ID(request))    print(我是test视图。。。)    return httpResponse(ok)

用浏览器去访问

结果:

74576400这是中间件1中的process_request方法74576400我是test视图。。。

我们可以从上面的结果中得到一下信息

1.process_request的执行时间,在视图函数执行之前执行

2.process_request里的参数request和视图函数里的request是一样的

那如果有两个中间件,他们的执行顺序是什么呢?,在添加一个中间件,在注册的时候,放到上面

from django.utils.deprecation import MIDdlewareMixinfrom django.shortcuts import httpResponse,render,redirectclass MIDdle1(MIDdlewareMixin):  # 需要继承这个类    def process_request(self,request):        print(ID(request))        print(这是中间件1中的process_request方法)        return httpResponse(mIDdle1)class MIDdle2(MIDdlewareMixin):    def process_request(self,request):        print(这是中间件2中的process_request方法)

然后我们再用浏览器请求test视图,会发现浏览器页面显示了mIDdle1,控制台输出了

这是中间件2中的process_request方法72082704这是中间件1中的process_request方法

这是因为中间件的执行顺序是我们在setting.py注册时写的顺序,先执行mIDdle2,在执行mIDdle1,而中间件mIDdle1里有返回一个response,所以Django就不往下执行了

总结:

1.process_request的执行时间,在视图函数执行之前执行

2.process_request里的参数request和视图函数里的request是一样的

3.process_request的执行顺序是按照settings.py里的注册顺序执行的

4.如果中间件的返回值为None,则按照正常的流程走,如果中间件有返回response对象,当前中间件后面的中间件的process_request和process_response方法、视图函数都不执行,执行当前中间的process_response方法以及之前的中间的process_response方法

process_response

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

from django.utils.deprecation import MIDdlewareMixinfrom django.shortcuts import httpResponse,request):        print(这是中间件1中的process_request方法)    def process_response(self,response):        print(这是中间件1中的process_response方法)        return responseclass MIDdle2(MIDdlewareMixin):    def process_request(self,request):        print(这是中间件2中的process_request方法)    def process_response(self,response):        print(这是中间件2中的process_response方法)        return response

结果:

这是中间件2中的process_request方法这是中间件1中的process_request方法我是test视图。。。这是中间件1中的process_response方法这是中间件2中的process_response方法

因为我们中间件的注册是mIDdle2在上面,所以请求来了之后先执行mIDdle2的process_request方法,然后执行mIDdle1的process_request方法,在执行视图函数,视图函数执行完之后在从注册的中间件里从下往上执行,因为mIDdle1在最下面,所以先执行mIDdle1的process_response方法。

我们在mIDdle1里的process_request里加个return,在来看看效果

class MIDdle1(MIDdlewareMixin):    def process_request(self,request):        print(这是中间件1中的process_request方法)        return httpResponse(mIDdle1)  # 增加这句    def process_response(self,response):        print(这是中间件1中的process_response方法)        return response

结果:页面返回了mIDdle1

这是中间件2中的process_request方法
这是中间件1中的process_request方法
这是中间件1中的process_response方法
这是中间件2中的process_response方法

这是因为请求执行mIDdle2中的process_request方法,然后执行mIDdle1里的process_request方法,因为mIDdle1的process_request方法里有return,所以就不执行视图函数,接着按照注册中间件的逆序执行process_response方法

 

那我们把这句放到mIDdle2里的process_request里,在来看看

class MIDdle2(MIDdlewareMixin):    def process_request(self,request):        print(这是中间件2中的process_request方法)        return httpResponse(mIDdle2)  # 增加这句    def process_response(self,response):        print(这是中间件2中的process_response方法)        return response

结果:

这是中间件2中的process_request方法这是中间件2中的process_response方法

代码解释:请求来了之后,先执行mIDdle2里的process_request方法,因为这里有return,所以就直接执行这里的process_response方法,然后再执行这个中间件上面的process_response方法

总结:

1.process_response在视图函数执行之后执行

2.process_response的参数,request,视图函数中用到的request,response,视图函数中返回的response

3.返回值必须是response对象,不能为None

4.process_response的执行执行顺序是按照注册顺序倒序执行

process_vIEw

process_vIEw有四个参数

request是httpRequest对象,和之前的是一样的

vIEw_func是Django即将使用的视图函数

vIEw_args是传递给视图函数的位置参数列表

vIEw_kwargs是传递给视图函数的关键字参数

Django会在调用视图函数之前执行process_vIEw方法

from django.utils.deprecation import MIDdlewareMixinfrom django.shortcuts import httpResponse,response):        print(这是中间件1中的process_response方法)        return response    def process_vIEw(self,vIEw_kwargs):        print(这是中间件1中的process_vIEw方法)class MIDdle2(MIDdlewareMixin):    def process_request(self,response):        print(这是中间件2中的process_response方法)        return response    def process_vIEw(self,vIEw_kwargs):        print(这是中间件2中的process_vIEw方法)

结果:

这是中间件2中的process_request方法这是中间件1中的process_request方法这是中间件2中的process_vIEw方法这是中间件1中的process_vIEw方法我是test视图。。。这是中间件1中的process_response方法这是中间件2中的process_response方法

process_vIEw是在process_request方法执行之后,视图函数执行之前执行的,是按照中间件注册顺序从上往下执行的

在process_vIEw加个return来看看

from django.utils.deprecation import MIDdlewareMixinfrom django.shortcuts import httpResponse,redirectclass MIDdle1(MIDdlewareMixin):    def process_request(self,vIEw_kwargs):        print(这是中间件1中的process_vIEw方法)class MIDdle2(MIDdlewareMixin):    def process_request(self,vIEw_kwargs):        print(这是中间件2中的process_vIEw方法)        return httpResponse(vIEw2)  # 增加这句

结果:

这是中间件2中的process_request方法这是中间件1中的process_request方法这是中间件2中的process_vIEw方法这是中间件1中的process_response方法这是中间件2中的process_response方法

代码解释:

先按照中间件的注册顺序,从上往下执行process_request方法(没有return,有return,直接执行该中间件对应的process_response方法)。然后从上往下执行process_vIEw方法,如果某一个process_vIEw方法里有return,则不执行后面的process_vIEw方法,直接从下往上执行process_response方法

 总结:

1.process_vIEw的执行时间,是在process_request之后,以及路由匹配之后,在视图函数之前执行

2.参数:request和之前的一样,vIEw_func要执行的视图函数,vIEw_args视图函数的位置参数,vIEw_kwargs视图函数的关键字参数

3.返回值:None正常走,httpResponse对象,后面的process_vIEw不执行,直接执行process_response方法(从下往上)

4.执行顺序按照中间件的注册顺序从上往下执行

process_exception

process_exception有两个参数,一个上httpRequest对象,一个exception上视图函数异常产生的Exception对象

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

from django.utils.deprecation import MIDdlewareMixinfrom django.shortcuts import httpResponse,vIEw_kwargs):        print(这是中间件1中的process_vIEw方法)    def process_exception(self,exception):        print(这是中间件1中的process_exception方法)class MIDdle2(MIDdlewareMixin):    def process_request(self,vIEw_kwargs):        print(这是中间件2中的process_vIEw方法)    def process_exception(self,exception):        print(这是中间件2中的process_exception方法)

视图函数如果正常的话

这是中间件2中的process_request方法这是中间件1中的process_request方法这是中间件2中的process_vIEw方法这是中间件1中的process_vIEw方法我是test视图。。。这是中间件1中的process_response方法这是中间件2中的process_response方法

往视图函数里写点异常在看看结果

def test(request):    print(我是test视图。。。)    int(weewe)    return httpResponse(ok)

结果:

这是中间件2中的process_request方法这是中间件1中的process_request方法这是中间件2中的process_vIEw方法这是中间件1中的process_vIEw方法我是test视图。。。这是中间件1中的process_exception方法这是中间件2中的process_exception方法Internal Server Error: /test/Traceback (most recent call last):  file "C:\Users\administrator\AppData\Local\Programs\Python\python36-32\lib\site-packages\django\core\handlers\exception.py",line 41,in inner    response = get_response(request)  file "C:\Users\administrator\AppData\Local\Programs\Python\python36-32\lib\site-packages\django\core\handlers\base.py",line 187,in _get_response    response = self.process_exception_by_mIDdleware(e,request)  file "C:\Users\administrator\AppData\Local\Programs\Python\python36-32\lib\site-packages\django\core\handlers\base.py",line 185,in _get_response    response = wrapped_callback(request,*callback_args,**callback_kwargs)  file "E:\django-project\orm_project\appTest01\vIEws.py",line 55,in test    int(weewe)ValueError: invalID literal for int() with base 10: weewe这是中间件1中的process_response方法这是中间件2中的process_response方法[26/Jul/2019 23:12:45] "GET /test/ http/1.1" 500 69084

执行视图函数,遇到异常之后执行process_exception方法,按注册的顺序从下往上执行,执行完之后在执行process_response(从上往下)

 

那如果有return了呢,因为是从下往上执行的,我们给mIDdle1加上return

结果:

这是中间件2中的process_request方法这是中间件1中的process_request方法这是中间件2中的process_vIEw方法这是中间件1中的process_vIEw方法我是test视图。。。这是中间件1中的process_exception方法这是中间件1中的process_response方法这是中间件2中的process_response方法

当遇到process_exception里的return时,注册顺序之前的中间件的process_exception方法不走了。执行所有中间件的process_response方法

总结:

1.process_exception的执行条件是有异常时才会执行,在视图函数之后,在process_response之前

2.参数exception错误对象信息

3.返回值:None,正常走。httpResponse对象,注册顺序之前的中间件的process_exception方法不走了。执行所有中间件的process_response方法,把process_exception里的返回值显示在浏览器上

4.执行顺序:按照注册顺序倒序执行

process_template_response

process_template_response(self,response)

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

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

from django.utils.deprecation import MIDdlewareMixinfrom django.shortcuts import httpResponse,exception):        print(这是中间件1中的process_exception方法)    def process_template_response(self,response):        print("这是中间件1中的process_template_response方法")        return responseclass MIDdle2(MIDdlewareMixin):    def process_request(self,exception):        print(这是中间件2中的process_exception方法)        return httpResponse(str(exception))    def process_template_response(self,response):        print("这是中间件2中的process_template_response方法")        return response

视图函数

def test(request):    print(我是test视图。。。)    def render():        print("我是render")        return httpResponse("render。。。")    res = httpResponse("OK")    res.render = render    return res

结果:

这是中间件2中的process_request方法这是中间件1中的process_request方法这是中间件2中的process_vIEw方法这是中间件1中的process_vIEw方法我是test视图。。。这是中间件1中的process_template_response方法这是中间件2中的process_template_response方法我是render这是中间件1中的process_response方法这是中间件2中的process_response方法

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

 中间件的执行流程

我们了解了中间件的五个方法,以及什么时候执行,参数,返回值

请求在到达中间件之后,先按照正序执行每个中间件中的process_request方法,如果process_request返回的是None,就依次执行。如果返回的是httpResponse对象,不在执行后面的 process_request方法,而是执行当前中间件对应的process_response方法,将httpResponse对象返回给浏览器。也就是说,如果MIDDLEWARE中注册了6个中间件,执行过程中,第3个中间件返回了一个httpResponse对象,那么第4,5,6中间件的process_request和process_response方法都不执行,顺序执行3,2,1中间件的process_response方法。

process_request方法都执行完后,匹配路由,找到要执行的视图函数,找到之后先不执行视图函数,先执行中间件中的process_vIEw方法,process_vIEw方法如果返回None,继续按顺序执行,所有process_vIEw方法执行完 后执行视图函数。假如中间件中的第三个process_vIEw方法返回了一个httpResponse对象,则4,5,6的processs_vIEw以及视图函数都不执行,直接从最后一个中间件,也就是中间件6的process_response方法开始倒序执行

process_template_response和process_exception两个方法的触发是有条件的,执行顺序也是倒序,总结所有的执行流程如下

Django请求流程图

总结

以上是内存溢出为你收集整理的django -- 中间件全部内容,希望文章能够帮你解决django -- 中间件所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/1195391.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-06-03
下一篇2022-06-03

发表评论

登录后才能评论

评论列表(0条)

    保存