目录
django中间件
中间件简介
1.流程图--介绍中间件
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',
]
这七个中间件程序会在请求来时自上而下依次的处理request请求,在响应走时自下而上依次处理response响应。
3.中间件的功能
网站访问频率的校验 用户权限的校验等全局类型的功能需求
4.前期我们要访问post请求,中间件的第四个字符串妨碍了简单post请求,初期阶段我们将其注释掉了。
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',
]
5.解析中间件原理
这七个字符串实际上对应的是中间件程序存储的路径
我们顺着路径的文件,点进去可知
由上述图可知,
1.七个中间件都继承了MiddlewareMixin类
2.都几乎有process_request和process_response函数
3.都必须传入参数
process_request需要传入request参数;
process_response需要传入request和response两个参数,必须返回response。
自定义中间件(重要)
如何自定义中间件
1.创建存储自定义中间件代码的py文件或者目录(如果中间件很多)
2.参考自带中间件的代码编写类并继承
3.在类中编写五个可以自定义的方法
4.一定在配置文件中注册中间件才可以生效
1,创建存储自定义中间件代码的py文件或者目录
2.编写自定义的中间件(在mymiddlie中编写MyMiddleware001)
3.编写好中间件,一定要去settings里的Middleware中注册自定义的中间件
中间件的顺序
我们只是定义了process_reqtest和process_response函数,我们想看看执行的顺序的,我们可以做一个小测试
mymiddle.py(自定义的中间件)
from django.utils.deprecation import MiddlewareMixin
class MyMiddleware001(MiddlewareMixin):
def process_request(self,request):
print('from MyMiddleware001 process_request')
def process_response(self,request,response):
print('from MyMiddleware001 process_response')
return response
class MyMiddleware002(MiddlewareMixin):
def process_request(self,request):
print('from MyMiddleware002 process_request')
def process_response(self,request,response):
print('from MyMiddleware002 process_response')
return response
当我们从网页向URL发送请求时,请求通过了网关接口到达了中间件,在中间件的执行过程是自上而下,从而经过路由层>>视图层>>>等,当响应是经过中间件的时候是自下而上的,返回给网关接口,再打包给浏览器,
后端打印
如果我们还想测试如果遇到HttpResponse对象,会怎么样?看下面的解释
django中间件两个基本方法
process_request
1.请求来的时候会从上往下依次经过每一个注册的中间件里面的该方法 如果没有则直接跳过
2.如果该方法自己返回了HttpResponse对象那么不再往后执行而是直接原路返回
如果请求遇到了process_request方法,该方法返回了HttpResponse对象,如下
class MyMiddleware001(MiddlewareMixin):
def process_request(self,request):
print('from MyMiddleware001 process_request')
return HttpResponse('你没有权限执行下面的中间件') # 遇到了HttpResponse对象
def process_response(self,request,response):
print('from MyMiddleware001 process_response')
return response
他经过的行径如黄色箭头,请求通过网关到中间件自上而下到达了中间件MyMiddleware001,就会直接执行MyMiddleware001的process_response方法,直接原路返回,不会走下面的中间件MyMiddleware002。
process_response
1.响应走的时候会从下往上依次经过每一个注册了的中间件里面的该方法 如果没有则直接跳过
2.该方法有两个先request和response 形参response指代的就是后端想要返回给前端浏览器的数据 该方法必须返回该形参 也可以替换
from django.utils.deprecation import MiddlewareMixin
from django.http import HttpResponse
class MyMiddleware001(MiddlewareMixin):
def process_request(self,request):
print('from MyMiddleware001 process_request')
def process_response(self,request,response):
print('from MyMiddleware001 process_response')
# return response
return HttpResponse('中间1直接返回了,返回了response')
注意:
1.一个请求经过了中间件,如果在执行process_request方法的时候直接返回了HttpResponse对象那么会原路返回执行自定义中间件的process_response 不是执行所有。
2.在flask中,是从最底层中间程序的响应函数开始执行的
django中间件三个了解得方法
1.process_view
路由匹配成功之后执行视图函数/类之前自动触发(顺序同process_request)
2.process_exception
视图函数/类执行报错自动触发(顺序同process_response)
3.process_template_response
视图函数/类返回的HttpResponse对象含有render并且对应一个方法的时候自动触发(顺序同process_response)
基于django中间件的功能设计
将各个功能制作成配置文件的字符串形式
1.如果想拥有该功能就要编写对应的字符串
2.如果不想有该功能则注释掉对应的字符串
中间件是如何实现字符串导入模块的?
importlib模块
importlib可以帮助我们用字符串导入模块,拿到一个模块名的字符串,它可以搜索模块,并执行导入操作:
import importlib # 引入模块
s1 = 'bbb.b' # aaa.bbb.ccc.b
res = importlib.import_module(s1) # from aaa.bbb.ccc import b
print(res) # <module 'bbb.b' from 'D:\\pythonProject03\\djangomiddle\\bbb\\b.py'>
s2 = 'aaa'
res=importlib.import_module(s2) # 相当于import aaa 并将模块设置为res
'''注意字符串的结尾最小单位只能是py文件 不能是py文件里面的变量名'''
思考1:思考django中间件是如何处理的(最小单位是类名)?
思考2:模拟编写一个消息通知功能(微信、qq、邮箱)?
方式一: 基于函数封装的版本
缺点: 没有眼前一亮的感觉,很一般
方式二: 基于django中间件的功能设计
优点: 眼前一亮,回味无穷
基于django中间件实现功能插拔式设计
1.importlib
通过字符串导入模块
2.从右开始切割字符串
rsplit
3.反射
将模块名看成是对象通过反射回去该模块中字符串对应的名字
4.面向对象的多态性
模块对象的反射
在python中一切皆对象,模块也是一种对象,模块的名称空间中的名字就是模块对象的属性。所以对于一个模块,我们可以通过反射的方式取到其中的类、函数、变量等名字:
仿django配置文件注册
知道以上两个知识点,我们也可以让仿中间件的注册过程,写好类后,用字符串保存路径,然后顺序执行。核心代码就是将字符串识别成可以执行的类程序:
# MyMiddleWare文件夹midware01.py中
class MidWare01(MiddlewareMixin):
def process_request(self, request):
print('from MidWare01 request')
# MyMiddleWare文件夹midware02.py中
class MidWare02(MiddlewareMixin):
def process_request(self, request):
print('from MidWare01 request')
# 注册配置
MIDWARE_LIST = [
'MyMiddleWare.midware01.MidWare01',
'MyMiddleWare.midware02.MidWare02',
]
# 按照注册顺序,执行每个类中的process_request方法
import importlib
def all_exec(request):
for full_path in MIDWARE_LIST:
# 将字符串切割为模块路径和类名
path, cls_name = full_path.rsplit('.', max_split=1)
# 通过模块路径字符串拿到模块名
module_name = importlib.import_module(path)
# 通过模块名反射拿到类名
cls = getattr(module_name, cls_name)
# 通过类产生对象
obj = cls()
# 通过对象使用方法
obj.process_request(request) # 多态的思想,因为大家的这个功能一致,所以方法名也该一致
标签:process,中间件,request,django,模块,response
From: https://www.cnblogs.com/zhanglanhua/p/17011036.html