一次请求的生命周期

我们先看客户端发起一次http请求的流程

注:django框架不包括socket, 要借助图中的两个模块来实现socket,进行客户端和服务端通信。wsgi性能较弱,一般测试开发用;企业中用uwsgi,性能强,并发好。

中间件

从图上可知,请求在到达视图之前,会依次执行中间件,视图返回的响应,依次倒序执行中间件。
在django中,中间件的是一个个的类,类中定义了一些方法。在django项目的setting.py文件中,有一个MIDDLEWARE列表,其中每一个元素都是一个中间件。

如果需要对请求作统一处理,比如在执行视图前,验证登录,日志记录,我们可以用装饰器,但是很麻烦,每个视图都要手动加装饰器语法。这时如果用中间件会更方便。

中间件的执行原理

从上图我们发现,MIDDLEWARE列表中的每一个元素都是字符串,那么Django是如何通过字符信息执行的中间件呢。

观察中间件元素发现由两部分构成:路径+类名;因此如果能分离出路径,并根据路径导入模块,然后执行模块中类的方法,就可以了。

关键问题是路径和类名都是字符串,通过字符串路径导入模块要借助importlib模块;在模块中通过字符串拿到类和在类中根据字符串拿到方法,都可以通过反射来做。

下面我们来自己模拟一下:

PLUGIN = {'disk': 'plugin.disk.Disk','memory': 'plugin.memory.Memory','network': 'plugin.network.Network',
}

这里用了字典的形式,原理是一样的。

import importlib  # 通过字符串导入模块for k, v in PLUGIN.items():# 分离模块路径 和 类名:# 'plugin.disk.Disk'  --> 模块路径'plugin.disk' 类名 'Disk' (结果都是字符串)# 通过字符串路径导入模块 importlib# 通过反射获取模块中的类module_name, cls_name = v.rsplit('.', maxsplit=1)module = importlib.import_module(module_name)cls = getattr(module, cls_name)obj = cls() # 实例化对象res = obj.method() # 调用对象的绑定方法

自定义中间件

下面我们自定义一个中间件,用于用户验证:

from django.utils.deprecation import MiddlewareMixin  # 导入类class M1(MiddlewareMixin):  # 自定义类,继承MiddlewareMixindef process_request(self, request):print('--- 自定义中间件进行登录验证 ---')# 如果访问路径是login函数,放行;否则验证session信息if request.path_info == 'login.html':return Nonefrom django.shortcuts import redirectif not request.session.get('user_info'):return redirect('/login.html')def process_response(self, request, response):print('自定义逻辑')return response 

注意,新版django可能无法导入,因此,直接把MiddlewareMixin类拿过来继承就好了:

class MiddlewareMixin(object):def __init__(self, get_response=None):self.get_response = get_responsesuper(MiddlewareMixin, self).__init__()def __call__(self, request):response = Noneif hasattr(self, 'process_request'):response = self.process_request(request)if not response:response = self.get_response(request)if hasattr(self, 'process_response'):response = self.process_response(request, response)return responseclass M1(MiddlewareMixin):  # 自定义类,继承MiddlewareMixin......

注意,自定义类时,类中的方法和参数都是固定的。
定义完成后,在setting.py中找到MIDDLEWARE列表,将我们刚刚自定义的中间件路径添加进去:

这样,每次请求进来,都会先执行自定义的中间件。

中间件中的方法

  • process_request 请求进来时执行;不能有返回值,一旦某个中间件的process_request 有返回值,那么下面的中间件就不走了,后面的url路由,视图函数更不会执行,直接执行当前中间件的process_response方法,层层往上返回这个返回值(如果process_response返回了其它值,或者上面的中间件返回了其它值,最后执行的返回值会覆盖之前的返回值。
class M1(MiddlewareMixin):def process_request(self, request, response):from django.shortcuts import HttpResponseallowed_ip = ['192.168.0.11',]# 维护一个允许/禁止访问的ip地址列表,判断请求ip, 放行/阻拦if request.META.get('REMOTE_ADDR') not in allowed_ip:return HttpResponse('请回去吧')else:return Nonedef process_response(self, request, response):return response
  • process_response 返回响应时执行,默认情况下返回response, 即视图函数的返回值,如果在这个方法中自定义了返回值,将返回自定义返回值。
class M1(MiddlewareMixin):def process_response(self, request, response):print('自定义逻辑')return response
  • process_view
class M1(MiddlewareMixin):def process_view(self, request, view_func, view_func_args, view_func_kwargs):print('M2.process_view')

执行时机:执行完process_request – > 路由分发, – > process_view –> 视图函数 –> process_response。process_view一旦有返回值,那么跳过下面的中间件,开始从视图层层往上,返回响应。假设有多个中间件,每个中间件中都定义了以上三个方法,那么django执行中间件的逻辑其实相当于将每个中间件中的一类方法放到一个列表里,一共3个列表,循环列表执行其中的方法,过程如下:

for process_request in process_request_list:process_request()执行路由分发 urlfor process_view in process_view_list:process_view()执行视图 func()for process_response in process_response_list:process_response()
  • process_exception 默认不执行;如果视图中出现异常,就会被执行。应用场景:自定义一个”更友好“的错误页面;
class M2(MiddlewareMixin):def process_exception(self, request, exception):from django.shortcuts import HttpResponsereturn HttpResponse('开发该功能的程序员已被关小黑屋')
  • process_template_response 默认不执行;如果返回的对象有render方法,就会被执行。不常用。
class MyResponse(object): # 我们可以在自定义类中对响应作进一步处理def __init__(self, response):self.response = responsedef render(self):return self.responsedef demo(request):response = HttpResponse('OK')return MyResponse(response) # 将响应作为字定类的的对象返回,拥有render方法

Django(五)中间件相关推荐

  1. {Django基础九之中间件} 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证...

    Django基础九之中间件 本节目录 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证 六 xxx 七 xxx 八 xxx 一 前戏 我们在前面的课程中已经学会了 ...

  2. Django的中间件

    Django的中间件 目录 中间件介绍 什么是中间件? 自定义中间件 自定义一个中间件示例 process_request process_response process_view process_ ...

  3. Django之中间件,csrf跨站伪造请求,auth认证模块

    Django请求生命周期 django的中间件 django的中间件相当于保安,请求的时候要经过django的中间件才能连接django的后端 能用来干什么:能够做网站的全局身份认证,访问频率,权限认 ...

  4. 07 Django组件-中间件

    中间件 方式一:函数式:中间件[middleware],也叫钩子方法[钩子函数],hook Django中的中间件是一个轻量级.底层的插件系统,可以介入Django的请求和响应处理过程,修改Djang ...

  5. 13 Django之中间件

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

  6. python 全栈开发,Day87(ajax登录示例,CSRF跨站请求伪造,Django的中间件,自定义分页)...

    python 全栈开发,Day87(ajax登录示例,CSRF跨站请求伪造,Django的中间件,自定义分页) 一.ajax登录示例 新建项目login_ajax 修改urls.py,增加路径 fro ...

  7. django框架--中间件系统

    目录 零.参考 一.中间件的基本理解 二.中间件的系统定位 三.中间件的配置 四.中间件的执行流程 五.中间件与装饰器之间的思考 六.中间件的应用场景 七.内置中间件 八.总结 零.参考 https: ...

  8. 浅谈Django的中间件与Python的装饰器

    浅谈Django的中间件 与Python的装饰器 一.原理 1.装饰器是Python的一种语法应用,利用闭包的原理去更改一个函数的功能,即让一个函数执行之前先到另外一个函数中执行其他需求语句,在执行该 ...

  9. Django 组件- 中间件

    11.1 中间件 一.中间件的概念 中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出.因为改变的是全局,所以需要谨 ...

  10. Django之中间件

    一.CBV加装饰器 第一种 @method_decorator(装饰器) 加在get上第二种 @method_decorator(login_auth,name='get') 加在类上第三种 @met ...

最新文章

  1. 北大智能学院成立!AI视觉泰斗朱松纯教授任院长
  2. 小米MixPath复现之旅
  3. mysql的存储覆盖_mysql覆盖存储
  4. gj3 Python数据模型(魔法函数)
  5. 处理SAP Netweaver gateway service使用过程中遇到的404 error
  6. Storm tick 功能
  7. centos中多台主机免密登录_centos免密码使用密钥登录
  8. 计算程序/函数运行时间
  9. [培训-无线通信基础-6]:信道编码(分组码、卷积吗、Polar码、LDPC码、Turbo码)
  10. oracle密码过期处理方法
  11. APS计划排程和生产排产系统,包含哪些排程算法?
  12. uc通讯不成功php版本过高,UC通信失败怎么办
  13. python 端口扫描_使用 python-nmap 进行端口扫描
  14. 踩坑指南!anaconda新建环境出错解决!又是猛男落泪的一天!
  15. 2019冬季PAT甲级
  16. JavaScript高级教程(25)——ES6
  17. testflight无法联网怎么办_Testflight不可用怎么办?
  18. Service START_NOT_STICKY、START_STICKY
  19. Git学习笔记:中国版GItHub,码云
  20. mysql查指定日期后的数据_mysql查询指定日期数据

热门文章

  1. 【C语言重点难点精讲】C语言指针
  2. 4-1:TCP协议之传输层的作用及传输层协议TCP和UDP
  3. 快速幂运算 《挑战程序设计竞赛》
  4. VC++CopyFile函数的用法
  5. python twised系列教程四–twisted Poetry client
  6. 7. OD-破解收费版限制天数的软件
  7. Java实现 栈 和 队列
  8. 再谈节奏与动力---平淡与枯燥的力量
  9. SP2010开发和VS2010专家食谱--第四章节—列表定义和内容类型(7)--创建列表定义...
  10. 只运行一个实例的写法