21 参考中间件,实现可插拔式设计
一、前言
什么是可插拔式设计?
在我们前面学习的django的内容,在django框架中,我们学习到了中间件,中间件是干嘛的,都还记得把!!
中间件是当请求来的时候,全局的对每一个request进行一个验证,我们都知道在Django的中间件中,有7个默认的中间件,而当一个request来的时候,这个request要依次经过每一个中间件的校验,当这个request对应的response走的时候,又要按照中间件列表的顺序进行倒叙执行中间件
在我们最开始用form表单提交数据的时候,我们好像是要把一个叫csrf的中间件给注释掉,然后form表单才能去提交post请求,也就是说当注释掉这个叫csrf的中间件的时候,request请求来的时候,这个request就不会经过这个中间件的校验了,而当我们把这个csrf的中间件注释解开的时候,我们发现request请求有经过这个中间件的校验了。这就叫可插拔式设计
二、可插拔式需要用到的方法
1. 可插拔式设计的代码,一定要是面向对象的
2.用到一个
3.用到反射getattr()
三、实例
我们现在有一个公司,现在公司有一个需求,因为今天是10月的最后一天,公司准备给每一个工作人员通过qq、手机短信、微信的方式,给工作人员发三太难短信,
然后,到11月份的月底,公司只想通过微信,qq的方式来发送信息了,这该怎么样设计一个可插拔是的程序呢?---根据django中间件的思想
1.我们先用面向对象来写着三个发消息的共功能
# 面向对象的鸭子类型
# 只要长得像,就是鸭子类型
# 就是有很多个类,但是这些个类都具有同样的方法名,但是呢?它的方法名实现的功能不一样,就是鸭子类型
# QQ 消息
class QQ:
# 实例化类的时候触发
def __init__(self,name):
self.name = name
# 对象的绑定方法
# 也是鸭子类型的方法
def send_msg(self,content):
print('QQ今天是10月的最后一天,请好好{}'.format(content))
# 微信 消息
class Wechat:
# 对象实例化的时候触发
def __init__(self,name):
self.name = name
# 鸭子类型的方法,对象的绑定方法
def send_msg(self,content):
print('Wechat今天是10月的最后一天,请好好{}'.format(content))
# Phone 短信
class Phone:
def __init__(self,name):
self.name = name
# 鸭子类型
def send_msg(self,content):
print('Phone今天是10月的最后一天,请好好{}'.format(content))
从上面我们写的类中,三种发送消息的类,可以看到send_msg就是鸭子类型的方法,
我们将上面的每一个类都放在不同的.py文件里
为什么放在一个包里呢?因为在settings配置里面。我们要导入这几个文件,导入一个文件他就是一个模块,那作为一个模块,当然要放在包里了,__init__.py文件里,from msg_bag import *
那这三个类都写好了,我们知道django中间件是则settings里配置了一个列表,这个列表就是放着一个个字符串一行的类,
那这里,我们也将这三个类放在setting文件中,当然首先的自己新建一个settings配置文件啦
# settings.py
FUNC_LIST = [
'msg_bag.phone.Phone',
'msg_bag.qq.QQ',
'msg_bag.wechat.Wechat',
]
# 启动文件
import setting # 将配置文件导进来
import importlib # 将这个模块导入
def run(content):
# 循环settings配置文件里的类的模块列表
'''
FUNC_LIST = [
'msg_bag.phone.Phone',
'msg_bag.qq.QQ',
'msg_bag.wechat.Wechat',
'''
for func in setting.FUNC_LIST:
# 将每一个字符串拿出来,然后根据.切割,从末尾切割一个
model,class_name = func.rsplit('.',maxsplit=1)
print(model) # msg_bag.phone \ msg_bag.qq \ msg_bag.wechat
print(class_name) # Phone \ QQ \ Wechat
# 利用importlib模块
mod = importlib.import_module(model)
'''
等同于
form msg_bag import phone
form msg_bag import qq
form msg_bag import wechat
'''
# 通过反射class_name是不是mod的类,然后取值赋给class_obj
class_obj = getattr(mod, class_name)
# 通过类去调用对象的绑定方法,将类自己传给send_msg
class_obj.send_msg(class_obj,content)
run('开开心心')