阅读 5448

Keeping up with the django - 插拔式设计 | Python 主题月

本文正在参加「Python主题月」,详情查看 活动链接

微信公众号搜索【程序媛小庄】 - 没有白走的路,每一步都算数

前言

在django全栈项目中,前端向后端提交post请求时需要注释csrf校验,将代码注释之后就无需进行校验了,如何实现只注释一行代码就可以注释掉整个功能呢?本文将介绍插拔式设计是如何实现的?

插拔式设计

插拔式设计实现需要借助一个模块importlib,该模块可以将字符串类型的路径转换为导入模块的语法格式。

# 导入模块的常规写法
from module import object

# 使用importlib
import importlib
res = 'myfile.test'
ret = importlib.import_module(res)  # from myfile import b
复制代码

可以通过这种代码设计方式模拟一下通知消息,简约版微信 QQ 短信等同时发送,并且可以很方便的关闭某一种通知渠道。

方式一:常规思路

创建一个py文件,将每个功能定义为一个函数,再创建一个启动文件,将定义的功能导入,在启动文件中运行。

myfile文件夹
- notify.py

def wechat(content):
    print(f'微信通知:{content}')


def message(content):
    print(f'短信通知:{content}')

def qq(content):
    print(f'qq通知{content}')
    
    
- start.py
import notify

def send(content):
    notify.wechat(content)
    notify.message(content)
    notify.qq(content)

if __name__ == '__main__':
    send('下课啦')
复制代码

方式二:面向对象

  • 借鉴django中间件的思路,每个功能独享一个py文件,全部放在一个目录下。
  • 创建一个settings.py配置文件,将需要被导入的模块中的具体对象的路径以字符串的方式写入列表。
  • 在存放功能的文件夹下的每个py文件都是一个功能模块,所以该文件夹就是一个包,所以就需要在该文件夹下在创建__init__.py文件,将每一个功能模块的名字都放在该py文件下
  • __init__.py文件中,通过for循环 + 鸭子类型 +字符串方法+反射就可以实现django中settings.py中只需要添加注释或者解除注释就可以实现某种功能的添加或者删除
# notify文件夹就是包
- email.py

class Email():
    def __init__(self):
        # 调用应用接口
        pass
    def send(self,content):
        print(f'email{content}')
        
- qq.py
class QQ():
    def __init__(self):
        # 调用应用接口
        pass
    def send(self,content):
        print(f'qq{content}')
        
-wechat.py
class Wechat():
    def __init__(self):
        # 调用应用接口
        pass
    def send(self,content):
        print(f'wechat{content}')
    

- settings.py

NOTIFY_LIST = [
    'notify.email.Email',
    'notify.qq.QQ',
    'notify.wechat.Wechat'
]

- __init__.py

import settings
import importlib


def send_all(content):
    for path_str in settings.NOTIFY_LIST:  #'notify.email.Email'
        module_path,class_name = path_str.rsplit('.',maxsplit=1)
        # module_path = 'notify.email'  class_name = 'Email'
        # 1 利用字符串导入模块
        module = importlib.import_module(module_path)  # from notify import email
        # 2 利用反射获取类名
        cls = getattr(module,class_name)  # Email、QQ、Wechat
        # 3 生成类的对象
        obj = cls()
        # 4 利用鸭子类型直接调用send方法
        obj.send(content)
        
        
- start.py

import notify
if __name__ == '__main__':
    notify.send_all('haha')
复制代码

结语

文章首发于微信公众号程序媛小庄,同步于掘金

码字不易,转载请说明出处,走过路过的小伙伴们伸出可爱的小指头点个赞再走吧(╹▽╹)

image.png

文章分类
后端
文章标签