我的第一个python web开发框架(27)——定制ORM(三)
在上一章中,我们已经创建好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/
我的第一个python web开发框架(27)——定制ORM(三)的更多相关文章
- 我的第一个python web开发框架(41)——总结
我的第一个python web开发框架系列博文从17年6.7月份开始写(存了近十章稿留到9月份才开始发布),到今天结束,一年多时间,想想真不容易啊. 整个过程断断续续,中间有段时间由于工作繁忙停了好长 ...
- 我的第一个python web开发框架(14)——后台管理系统登录功能
接下来正式进入网站的功能开发.要完成后台管理系统登录功能,通过查看登录页面,我们可以了解到,我们需要编写验证码图片获取接口和登录处理接口,然后在登录页面的HTML上编写AJAX. 在进行接口开发之前, ...
- 我的第一个python web开发框架(1)——前言
由于之前经验不是很丰富,写的C#系统太过复杂,所以一直想重写,但学的越多越觉得自己懂的越少,越觉的底气不足.所以一直不敢动手,在内心深处对自己讲,要静下心来认真学习,继续沉淀沉淀.这两年多以来找各种机 ...
- 我的第一个python web开发框架(3)——怎么开始?
小白与小美公司经过几次接触商谈,好不容易将外包签订了下来,准备开始大干一场.不过小白由于没有太多的项目经验,学过python懂得python的基本语法,在公司跟着大家做过简单功能,另外还会一些HTML ...
- 我的第一个python web开发框架(22)——一个安全小事故
在周末的一个早上,小白还在做着美梦,就收到了小美的连环追魂call,电话一直响个不停. 小白打着哈欠拿起电话:早上好美女. 小美:出事了出事了,我们公司网站一早访问是一片空白,什么内容都没有了,你赶急 ...
- 我的第一个python web开发框架(2)——一个简单的小外包
第一部分说明 第一部分大概有20来章,主要讲的是一些开发常识.开发前中后期准备内容.开发环境与服务器部署环境安装设置.python基础框架结构与功能等内容,代码会比较简单. 本系列会以故事的方式,向大 ...
- 我的第一个python web开发框架(6)——第一个Hello World
小白中午听完老菜讲的那些话后一直在思考,可想来想去还是一头雾水,晕晕呼呼的一知半解,到最后还是想不明白,心想:老大讲的太高深了,只能听懂一半半,看来只能先记下来,将明白的先做,不明白的等以后遇到再学. ...
- 我的第一个python web开发框架(7)——本地部署前端访问服务器
PS:本系列内容进度节奏会放的很慢,每次知识点都尽量少一点,这样大家接触的知识点少了,会更容易理解,因为少即是多.另外,对于后面代码部分,虽然尽量不用那些复杂的封装和类,但它并不表示看了就能全部记住, ...
- 我的第一个python web开发框架(10)——工具函数包说明(一)
PS:原先是想直接进入功能开发,要用到什么函数时再创建,这样也容易熟悉每个函数的由来和使用方法,但考虑到这样操作,到时会经常在不同文件间切换,不好描述,容易造成混乱,所以还是使用函数库这种方式来说明. ...
随机推荐
- JVM垃圾回收
1. 概念理解 1.1. 并行(Parallel)与并发(Concurrent) 并行:指多个垃圾收集线程并行工作,但此时用户线程仍然处于等待状态 并发:指用户线程与垃圾收集线程同时执行 1.2. ...
- 使用 SetColorFilter 神奇地改变图片的颜色
关键代码如下: colors.xml文件中定义一个颜色值: <color name="permission_dialog_img_color">#000000</ ...
- C语言实现顺序栈的初始化&进栈&出栈&读取栈顶元素
/*顺序表实现栈的一系列操作*/ #include<stdio.h> #include<stdlib.h> #define Stack_Size 50 //设栈中元素个数为50 ...
- .NET快速信息化系统开发框架 V3.2->Web版本新增“文件管理中心”集上传、下载、文件共享等一身,非常实用的功能
文件中心是3.2版本开始新增的一个非常实用功能,可以归档自己平时所需要的文件,也可以把文件分享给别人,更像一个知识中心.文件中心主界面如下图所示,左侧“我的网盘”展示了用户对文件的分类,只能自己看到, ...
- 从SQL Server CloudDBA 看云数据库智能化
最近阿里云数据库SQL Server在控制台推出了CloudDBA服务,重点解决数据库性能优化领域问题,帮助客户更好的使用好RDS数据库,这是继MySQL之后第二个关系型数据库提供类似的服务. 数 ...
- Joda-Time开源库
Joda-Time是一个面向 Java™ 平台的易于使用的开源时间日期库. 依赖 <dependency> <groupId>joda-time</groupId> ...
- Jenkins结合.net平台综合之监听git仓库并自动摘取最新代码编译
前面章节我们讲解了Jenkins结合.net平台工具以及一些第三方工具实现项目自动还原,自动编译,自动测试和自动发布.然而实现自动化还有一个关键的步骤就是监听源码仓库变化然后从仓库拉取最新代码,然后再 ...
- Linux和Shell回炉复习系列文章总目录
本页内容都是本人回炉Linux时整理出来的.这些文章中,绝大多数命令类内容都是翻译.整理man或info文档总结出来的,所以相对都比较完整. 本人的写作方式.风格也可能会让朋友一看就恶心到直接右上角叉 ...
- 使用EMQ搭建MQTT服务器
前言寒假的时候开始搭建mqtt服务器,一开始使用的是RabbitMQ,基于Erlang语言.但是RabbitMQ的本职工作是AMQP,MQTT只是他的一个插件功能,似乎有些大材小用,很多MQTT的功能 ...
- win10下rdlc报表在vs(visual studio)中中文显示小方块的批量处理解决方法
在网上找vs中rdlc报表显示中文时显示小方块的解决方案,无外就是修改文本框的字体属性.但是对于维护已有的rdlc报表时,有中文的地方(此时都显示了小方块)会很多,再一个一个设置实在太麻烦.所以自己花 ...