我的第一个python web开发框架(27)——定制ORM(三)

时间:2022-11-07 13:03:50

  在上一章中,我们已经创建好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': '', '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方法。

  

  本文对应的源码下载 (为了方便大家理解,源码包只放了这两章所用到的一些代码)

版权声明:本文原创发表于 博客园,作者为 AllEmpty 本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。

python开发QQ群:669058475(本群已满)、733466321(可以加2群)    作者博客:http://www.cnblogs.com/EmptyFS/