弄完底层数据库操作模块后, 接下来要做的是 ORM 的正式设计. 在开始之前, 我们需要思考一下怎么来设计一个 ORM 呢? 这个类它能帮助我们处理什么样的问题? 需要有哪些功能模块? 怎么做到针对不同的数据库与表单进行操作?
在前面我们知道, ORM 它简单的理解就是将我们写的一些参数值转变为对应的 sql 语句, 来对数据表进行增删改查的操作. 它可以帮助我们整合重复的代码, 让我们对数据库操作变的更加简单. 也就是说, 只需要将参数存储到对应的字典, 列表或元组中, 并将它们做为参数提交给 ORM,ORM 就会自动分析并处理, 然后生成对应的 sql 语句. 对于 Pythoner 来说, 字典, 列表和元组是我们最熟悉的变量, 操作它们会更加的熟悉, 而不是 sql 语句.
那么 ORM 应该拥有哪些功能模块? 我们可以从对数据库操作的角度进行思考, 我们对数据库的操作无非就是增删改查, 那么分解下来, 实际上就是我们所要实现的功能了. 比如说: 新增记录, 修改记录, 删除记录, 按指定条件查询, 查询指定主键记录, 判断记录是否存在, 查询数量统计, 查询指定值合计数, 获取指定字段最大值, 获取指定字段最小值...... 可以看到我们常用的查询还是挺多的, 只要将它们一一实现, 那么以后操作起这些功能就会变得更加的简单方便.
而对于有多数据库时, 我们只需要将 ORM 进行抽象创建一个 ORM 基类, 所有的数据表操作类继承它(每个数据表我们都需要独立创建一个对应的类, 它需要继承 ORM 基类来获取基类的所有能力), 在实例化数据表操作类时, 像上一章所讲到的那样通过参数注入方式处理, 即不同的数据库我们注入不同的数据库连接配置, 这样我们在实例化数据表操作类时, 就不必考虑它到底是属于那个数据库, 我们只需要知道每个表对于每个数据库来说都是唯一的, 在实例化时该操作类就会进行初始化操作, 然后自动载入对应的数据库配置, 当对这个表进行操作时, 它也会自动连接对应的数据库执行相关的操作了.(如下图)
根据上面的理解, 我们先创建一个 ORM 基类:_logic_base.py(也可以称为逻辑层父类)
- #!/usr/bin/env python
- # coding=utf-8
- from common import db_helper
- class LogicBase():
- """逻辑层基础类"""
- def __init__(self, db, table_name, column_name_list='*', pk_name='id'):
- """类初始化"""
- # 数据库参数
- self.__db = db
- # 表名称
- self.__table_name = str(table_name).lower()
- # 查询的列字段名称,* 表示查询全部字段, 多于 1 个字段时用逗号进行分隔, 除了字段名外, 也可以是表达式
- self.__column_name_list = str(column_name_list).lower()
- # 主健名称
- self.__pk_name = str(pk_name).lower()
- 子类在继承该类时, 通过对__init__()进行初始化, 将相关的参数注入进来, 在后续执行相关操作时, 就可以直接调用这些参数进行设置了. 例如我们创建一个 manager 表对应的操作类 ManagerLogic():
- #!/usr/bin/env python
- # coding=utf-8
- from logic import _logic_base
- from config import db_config
- # 获取数据库参数
- _db = db_config.DB
- class ManagerLogic(_logic_base.LogicBase):
- """用户管理表逻辑类"""
- def __init__(self):
- # 表名称
- __table_name = 'manager'
- # 初始化
- _logic_base.LogicBase.__init__(self, _db, __table_name)
- 通过 from logic import _logic_base 来导入父类, 被 ManagerLogic 类所继承.
- 然后导入配置文件 db_config, 获取数据库配置参数 db_config.DB.
- ManagerLogic 类在执行__init__()初始化时, 在第 18 行中绑定好该类对应的数据库(不同类可以绑定不同的配置文件, 即不同的数据库), 以及设置该类绑定的数据表名称(通过这里绑定, 在后续操作时就不会因为复制粘贴时不小时弄错表名了, 当然在创建数据表子类时也要小心不要绑错表名称了).
- column_name_list 是用于查询时, 如果不设置输出字段名, 则会默认使用这个变量做为参数, 方便有些表在操作时可以直接在这里设置好输出字段名的限制. 默认值为 *, 表示输出所有字段内容.
- pk_name 是数据表的主键名称, 默认为 id, 对于一些不以 id 为默认值的, 可以在这里进行设置为该表指定的主键名称.
- 做好这些, ManagerLogic 类就拥有了父类所有的能力 (方法) 了 -- 当然需要后面将父类的功能实现后才行.
- 比如父类拥有 get_model()方法
- def get_model(self):
- """通过条件获取一条记录"""
- return '获取一条记录'
- 那么我们可以写个测试用例, 通过下面方式来进行调用
- #!/usr/bin/evn python
- # coding=utf-8
- import unittest
- from logic import manager_logic
- class DbHelperTest(unittest.TestCase):
- """数据库操作包测试类"""
- def setUp(self):
- """初始化测试环境"""
- print('------ini------')
- def tearDown(self):
- """清理测试环境"""
- print('------clear------')
- def test(self):
- ##############################################
- # 只需要看这里, 其他代码是测试用例的模板代码 #
- ##############################################
- # 实例化 manager 表操作类 ManagerLogic
- _manager_logic = manager_logic.ManagerLogic()
- # 执行 get_model()方法, 获取记录实体
- model = _manager_logic.get_model()
- print(model)
- ##############################################
- if __name__ == '__main__':
- unittest.main()
输出结果:
------ini------
获取一条记录
------clear------
看起来是不是很简单.
来源: https://www.cnblogs.com/EmptyFS/p/9404658.html