在上一章中, 我们已经创建好 ORM 的基类了, 接下来要做的就是将基类的常用方法一一实现.
首先我们来看看之前项目中, 最常见的获取指定主键的记录实体
- @get('/api/product/<id:int>/')
- def callback(id):
- """
- 获取指定 id 的产品记录实体
- """ sql ="""select * from product where id = %s""" % (id,)
- # 读取记录
- result = db_helper.read(sql)
- if result:
- return web_helper.return_msg(0, '成功', result[0])
- else:
- return web_helper.return_msg(-1, "查询失败")
- 从代码中可以看到, 我们需要执行 select * from product where id = xx 从数据表中查询到我们想要的数据.
- 要封装成 ORM 的方法, 我需要需要注意下面几项事情:
- 1. 方法名必须是简单易懂的
- 2. 方法需要接收指定的主键值
- 3.sql 需要在方法中进行组装
- 根据这些要求, 我们可以很容易写出这个方法
- def get_model_for_pk(self, pk):
- """通过主键值获取数据库记录实体"""
- if not pk:
- return {}
- # 组装查询条件
- wheres = '%s = %s' % (self.__pk_name, str(pk))
- # 合成 sql 语句
- sql = "select %(column_name_list)s from %(table_name)s where %(wheres)s" % \
- {'column_name_list': self.__column_name_list, 'table_name': self.__table_name, 'wheres': wheres}
- # 初化化数据库链接
- with db_helper.PgHelper(self.__db, self.__is_output_sql) as db:
- # 执行 sql 语句
- _result = db.execute(sql)
- # 对返回的内容进行处理
- if _result:
- result = _result[0]
- else:
- result = {}
- return result
- 我们通过方法名 (get_model_for_pk) 应当可以知道, 我们是通过主键来获取指定的记录实体内容.
- 该方法需要传入的参数值是主键值 pk
- 在接收到主健值以后, 我们需要对它进行简单的判断处理, 如果它为空则直接返回空字典.
- 在组合 sql 前, 我们需要选对查询条件进行组装, 这里我们直接使用 self.__pk_name, 在上一章初始化时定义好的默认项, 在这里不直接使用 id 做为条件字段, 是为了当出现主键名称为其他字符时, 可以灵活处理. 比如订单表使用 code 为主键时, 就可以直接绑定 code 而不是自增 id 了. 比如 self.__pk_name 初始值是 id, 主键 pk 值是 1, 那么组装后的查询条件为 id=1
- 然后直接调用默认项查询字段名称 self.__column_name_list 和表名称 self.__table_name 来合成 sql 语句. 例如 self.__column_name_list 初始值为 *,self.__table_name 初始值为 product, 那么合成的 sql 语句为: select * from product where id=1
- 最后调用数据库操作类 db_helper 来执行 sql 语句(这里使用 widh 方法来初始化数据库操作类), 将执行后的结果返回主程序
- 针对上面这个读取产品记录实体的功能, 我们像上一章一样, 先创建好一个产品管理的逻辑类, 继承 ORM 基类
- #!/usr/bin/env python
- # coding=utf-8
- from logic import _logic_base
- from config import db_config
- class ProductLogic(_logic_base.LogicBase):
- """产品管理表逻辑类"""
- def __init__(self):
- # 表名称
- __table_name = 'product'
- # 初始化
- _logic_base.LogicBase.__init__(self, db_config.DB, db_config.IS_OUTPUT_SQL, __table_name)
- 我们就可以直接改造前面的接口调用代码了
- @get('/api/product/<id:int>/')
- def callback(id):
- """
- 获取指定记录
- """
- # 实例化 product 表操作类 ProductLogic
- _product_logic = product_logic.ProductLogic()
- # 执行 get_model_for_pk()方法, 获取记录实体
- model = _product_logic.get_model_for_pk(id)
- if model:
- return web_helper.return_msg(0, '查询成功', model)
- else:
- return web_helper.return_msg(-1, "查询失败")
- 和前面的代码比较, 代码看起来简单多了
- 直接上单元测试看看执行效果
- #!/usr/bin/evn python
- # coding=utf-8
- import unittest
- from logic import product_logic
- class DbHelperTest(unittest.TestCase):
- """数据库操作包测试类"""
- def setUp(self):
- """初始化测试环境"""
- print('------ini------')
- def tearDown(self):
- """清理测试环境"""
- print('------clear------')
- def test(self):
- ##############################################
- # 只需要看这里, 其他代码是测试用例的模板代码 #
- ##############################################
- # 实例化 product 表操作类 ProductLogic
- _product_logic = product_logic.ProductLogic()
- # 执行 get_model_for_pk()方法, 获取记录实体
- model = _product_logic.get_model_for_pk(2)
- print(model)
- ##############################################
- if __name__ == '__main__':
- unittest.main()
- 输出结果:
- ------ini------
- {'product_class_id': 1, 'place_of_origin': '广东广州', 'name': '饼干', 'id': 2, 'standard': '500g', 'is_enable': 1, 'add_time': datetime.datetime(2018, 7, 25, 23, 10, 4), 'quality_guarantee_period': '2018 年 12 月', 'code': '20180212321211', 'content': '产品描述', 'front_cover_img': 'http://xxx.com/xxx.jpg'}
- ------clear------
- 做到这一步, 一个简单的通过主键值读取数据表记录实体的 ORM 方法就完成了.
- 为了让这个读取记录实体的功能能应用的更加广泛, 我们还需要对它进行改造与加工.
- 在开始之前, 大家再继续思考一下, 我们获取记录实体, 通过主键查询只是众多方法中的其中一个, 我们还会经常使用各种条件的组合来进行查询, 读取记录实体, 所以这里我们可以实现自定义条件查询的方法
- def get_model(self, wheres):
- """通过条件获取一条记录"""
- # 如果有条件, 则自动添加 where
- if wheres:
- wheres = 'where' + wheres
- # 合成 sql 语句
- sql = "select %(column_name_list)s from %(table_name)s %(wheres)s" % \
- {'column_name_list': self.__column_name_list, 'table_name': self.__table_name, 'wheres': wheres}
- # 初化化数据库链接
- with db_helper.PgHelper(self.__db, self.__is_output_sql) as db:
- # 执行 sql 语句
- _result = db.execute(sql)
- # 对返回的内容进行处理
- if _result:
- result = _result[0]
- else:
- result = {}
- return result
- 代码看起来与前面的 get_model_for_pk()方法差不多, 只不过将 pk 参数改为条件参数 wheres, 不需要再组合主键查询条件而已. 由于两个函数部分代码一样, 所以我们需要对 get_model_for_pk()方法进行重构, 直接将组装好的查询条件提交给 get_model()方法来执行就可以了, 将它返回的内容直接返回给主程序.
- def get_model_for_pk(self, pk, wheres=''):
- """通过主键值获取数据库记录实体"""
- if not pk:
- return {}
- # 组装查询条件
- wheres = '%s = %s' % (self.__pk_name, str(pk))
- return self.get_model(wheres)
改造完成后, 使用前面的单元测试跑一下, 可以看到返回结果一样. 增加了 get_model()方法以后, 我们就可以灵活的自定义任意的查询条件来读取记录了. 这里要注意的是, 使用 get_model()方法查询时, 有可能在查询时会返回多条记录, 这个方法它只返回第一条记录. 需要返回多条记录时, 可以使用我们后续封装的其他 ORM 方法.
本文对应的源码下载 https://pan.baidu.com/s/1sY-ulHZlOuBgFymsy7d6jQ (为了方便大家理解, 源码包只放了这两章所用到的一些代码)
来源: https://www.cnblogs.com/EmptyFS/p/9410998.html