我的第一个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:原先是想直接进入功能开发,要用到什么函数时再创建,这样也容易熟悉每个函数的由来和使用方法,但考虑到这样操作,到时会经常在不同文件间切换,不好描述,容易造成混乱,所以还是使用函数库这种方式来说明. ...
随机推荐
- 前端(各种demo)二:左侧导航栏的折叠和打开(不使用js)基础版和升级版
1.给div设置定位. 复习一下—— css中position有五种属性: static:默认值,没有定位 absolute:绝对定位,相对于父级元素进行定位 relative:相对定位 fixed: ...
- RabbitMQ学习笔记(二) 工作队列
什么是工作队列? 工作队列(又名任务队列)是RabbitMQ提供的一种消息分发机制.当一个Consumer实例正在进行资源密集任务的时候,后续的消息处理都需要等待这个实例完成正在执行的任务,这样就导致 ...
- FloatingActionButton(悬浮按钮)使用学习<一>
FloatingActionButton简称FAB. 一. 对于App或某个页面中是否要使用FloatingActionButton必要性: FAB代表一个App或一个页面中最主要的操 ...
- Paramiko模块简单使用
介绍 Paramiko 一个第三方包,需要单独安装我们知道远程批量主机管理,比如ansible.Fabric,不需要安装客户端的远程执行命令等,这些都是基于Python原生的SSH,相当于模拟了一个S ...
- List-ArrayList集合基础增强底层源码分析
List集合基础增强底层源码分析 作者:Stanley 罗昊 [转载请注明出处和署名,谢谢!] 集合分为三个系列,分别为:List.set.map List系列 特点:元素有序可重复 有序指的是元素的 ...
- docker 复制镜像和复制容器
复制镜像和复制容器都是通过保存为新镜像而进行的. 具体为: 保存镜像 docker save ID > xxx.tar docker load < xxx.tar 保存容器 docker ...
- 经典面试题|讲一讲JVM的组成
JVM(Java 虚拟机)算是面试必问的问题的了,而但凡问 JVM 一定会问的第一个问题就是:讲一讲 JVM 的组成?那本文就注重讲一下 JVM 的组成. 首先来说 JVM 的组成分为,整体组成部分和 ...
- 第9章 使用客户端凭据保护API - Identity Server 4 中文文档(v1.0.0)
快速入门介绍了使用IdentityServer保护API的最基本方案. 我们将定义一个API和一个想要访问它的客户端. 客户端将通过提供ClientCredentials在IdentityServer ...
- win10下rdlc报表在vs(visual studio)中中文显示小方块的批量处理解决方法
在网上找vs中rdlc报表显示中文时显示小方块的解决方案,无外就是修改文本框的字体属性.但是对于维护已有的rdlc报表时,有中文的地方(此时都显示了小方块)会很多,再一个一个设置实在太麻烦.所以自己花 ...
- [Linux] 取两个文件的并集/交集/差集
uniq -d是只打印重复行 -u是只打印独一无二的行文件A : abcd文件B: cdef取并集:A + B sort A B|uniq 取交集: sort A B|uniq -d 取差集:A - ...