我的第一个python web开发框架(33)——接口代码重构
前面ORM模块我们已经完成了开发,接下来要做的就是对项目代码进行重构了。因为对底层数据库操作模块(db_helper.py)进行了改造,之前项目的接口代码全都跑不起来了。
在写ORM模块时,我们已经对产品接口的分页查询、新增、修改、获取指定产品实体接口已经重构好了,还剩下删除接口未完成
@delete('/api/product/<id:int>/')
def callback(id):
"""
删除指定记录
"""
# 编辑记录
sql = """delete from product where id=%s returning id"""
vars = (id,)
# 写入数据库
result = db_helper.write(sql, vars)
# 判断是否提交成功
if result:
return web_helper.return_msg(0, '成功')
else:
return web_helper.return_msg(-1, "删除失败")
如果前面代码有认真学习的小伙伴看到这段代码,要改成ORM方式应该很容易实现了
只需要将第7行到第10行替换对应的调用代码就可以了
@delete('/api/product/<id:int>/')
def callback(id):
"""
删除指定记录
"""
# 实例化product表操作类ProductLogic
_product_logic = product_logic.ProductLogic()
result = _product_logic.delete_model(id)
# 判断是否提交成功
if result:
return web_helper.return_msg(0, '成功')
else:
return web_helper.return_msg(-1, "删除失败")
首先是初始化产品逻辑层操作类,然后调用delete_model()这个方法就可以了
当你习惯这种写法以后,你会发现实现各个接口会变得非常的简单与方便,开发速度比之前也提升了很多
产品分类相关接口(product_class.py)与产品相关接口(product.py)功能差不多,具体实现我就不一一讲解了,大家可以自己试试
产品分类的删除分类接口大家会看到它的代码与产品删除接口差不多,不过多了一个该分类是否已经被引用的一个判断,对于这个下面专门说明一下
@delete('/api/product_class/<id:int>/')
def callback(id):
"""
删除指定记录
"""
# 判断该分类是否已经被引用,是的话不能直接删除
sql = """select count(*) as total from product where product_class_id=%s""" % (id,)
# 读取记录
result = db_helper.read(sql)
if result and result[0].get('total', -1) > 0:
return web_helper.return_msg(-1, "该分类已被引用,请清除对该分类的绑定后再来删除")
# 编辑记录
sql = """delete from product_class where id=%s returning id"""
vars = (id,)
# 写入数据库
result = db_helper.write(sql, vars)
# 判断是否提交成功
if result:
return web_helper.return_msg(0, '成功')
else:
return web_helper.return_msg(-1, "删除失败")
这段代码后半部分可以参考产品的删除接口实现,前半部分需要调用产品方法进行判断处理。
在编写时我们会发现,我们的ORM并没有直接判断记录是否存在的方法,只有一个用于获取指定条件记录数的方法。
一般来说,我们在开发时发现ORM没有自己想要的方法时,我们需要做以下思考:
1.有没有替代可以实现的方法存在
2.该功能是否是常用的功能,能否封装成公共方法,如果可以就将它封装到逻辑层基类(ORM模块)中去,让所有继承的子类都拥有这个功能
3.如果它只是对指定表单操作时才用到,就将它封装到该逻辑层子类,方便该子类要用到时可以随时调用
这段代码的要求是判断指定的分类是否被产品引用,抽象出来的意思就是判断指定条件的记录是否存在,对于这个功能有开发经验的小伙伴很容易判断它是很多地方都有可能要用到的通用方法,所以我们需要在ORM中增加一下这个方法。而我们ORM已经存在get_count()这个获取记录数的方法存在了,我们可以通过调用这个方法来判断记录数量是否大于0,来得出指定条件的记录是否存在这样的结果。
def exists(self, wheres):
"""检查指定条件的记录是否存在"""
return self.get_count(wheres) > 0
有了这个方法,我们就可以继续对产品分类删除接口进行改造了
@delete('/api/product_class/<id:int>/')
def callback(id):
"""
删除指定记录
"""
# 实例化product表操作类ProductLogic
_product_logic = product_logic.ProductLogic()
# 判断该分类是否已经被引用,是的话不能直接删除
if _product_logic.exists('product_class_id=' + str(id)):
return web_helper.return_msg(-1, "该分类已被引用,请清除对该分类的绑定后再来删除")
# 实例化product_class表操作类product_class_logic
_product_class_logic = product_class_logic.ProductClassLogic()
result = _product_class_logic.delete_model(id)
# 判断是否提交成功
if result:
return web_helper.return_msg(0, '成功')
else:
return web_helper.return_msg(-1, "删除失败")
通过这个例子,大家在实际开发过程中,可以灵活的根据自己需要,来增加或改造对应的底层方法,积累你自己的底层框架代码,那么随着开发时间的增加,你开发起各种功能来就会越加得心应手了。
细心的朋友会发现,ORM模块的缓存部分,多了一个get_model_for_cache_of_where()方法,下面我来说明一下它的用途。
我们在开发时,除了通过主键id来获取记录实体以外,在有的数据表中,还会存在第二个主键,或多个主键的情况,我们需要通过这些主键来获取对应的记录实休,比如说管理员或用户表中的登录账号字段;订单表中的订单编码字段等。
正常情况下,我们直接通过get_model()方法就可以读取对应的记录了,如果我们想减少数据库的查询,直接在缓存中如何使用呢?直接存取记录实体,由于这些额外的主键并没有与ORM中的编辑与删除操作关联,即在进行编辑与删除操作时不会同步更新用其他主键存储的实体内容,这样就会产生脏数据。所以我们可以换一种思路来实现,我们可以将这些额外的主键和对应的值生成缓存组合key,里面存储对应的记录实体id,也就是说在存储记录实体时,还是使用原来的主键id存储该实体,然后用额外主键和对应值生成缓存组合key中存储主键id,在获取记录实体时,先用这个组合key提取对应的id,再用这个id来获取记录实体。这个说明好像有点绕,大家自己debug一下就很容易明白其中的原理了,下面看代码:
def get_model_for_cache_of_where(self, where):
"""
通过条件获取记录实体————条件必须是额外的主键,也就是说记录是唯一的(我们经常需要使用key、编码或指定条件来获取记录,这时可以通过当前方法来获取)
:param where: 查询条件
:return: 记录实体
"""
# 生成实体缓存key
model_cache_key = self.__table_name + encrypt_helper.md5(where)
# 通过条件从缓存中获取记录id
pk = cache_helper.get(model_cache_key)
# 如果主键id存在,则直接从缓存中读取记录
if pk:
return self.get_model_for_cache(pk) # 否则从数据库中获取
result = self.get_model(where)
if result:
# 存储条件对应的主键id值到缓存中
cache_helper.set(model_cache_key, result.get(self.__pk_name))
# 存储记录实体到缓存中
self.set_model_for_cache(result.get(self.__pk_name), result)
return result
下面改造调用例子(请查看login.py第35行附近)
##############################################################
### 获取登录用户记录,并进行登录验证 ###
##############################################################
sql = """select * from manager where login_name='%s'""" % (username,)
# 从数据库中读取用户信息
manager_result = db_helper.read(sql)
# 判断用户记录是否存在
if not manager_result:
return web_helper.return_msg(-1, '账户不存在')
我们可以改造为:
##############################################################
### 获取登录用户记录,并进行登录验证 ###
##############################################################
_manager_logic = manager_logic.ManagerLogic()
# 从数据库中读取用户信息
manager_result = _manager_logic.get_model_for_cache_of_where('login_name=' + string(username))
# 判断用户记录是否存在
if not manager_result:
return web_helper.return_msg(-1, '账户不存在')
还有登录接口最底部,更新管理员最后登录时、登录ip和累加登录次数需要改造,具体代码如下:
##############################################################
### 更新用户信息到数据库 ###
##############################################################
# 更新当前管理员最后登录时间、Ip与登录次数(字段说明,请看数据字典)
sql = """update manager set last_login_time=%s, last_login_ip=%s, login_count=login_count+1 where id=%s"""
# 组合更新值
vars = ('now()', ip, manager_id,)
# 写入数据库
db_helper.write(sql, vars)
我们可以更改为:
##############################################################
### 更新用户信息到数据库 ###
##############################################################
# 更新当前管理员最后登录时间、Ip与登录次数(字段说明,请看数据字典)
fields = {
'last_login_time': 'now()',
'last_login_ip': string(ip),
'login_count': 'login_count+1',
}
# 写入数据库
_manager_logic.edit_model(manager_id, fields)
对于字段值,如果为字符串、具体时间、json等类型的,也就是说需要用单撇号括起来的,我们就需要调用string_helper模块的string方法进行转换,它可以为变量增加单撇号,如果直接赋字符串值,生成的sql语句是没有单撇号的,这里要注意一下
如果是数值类型,直接写值就可以了,当然直接赋字符串值也没有关系,因为生成sql是不会自动添加单撇号的
如果要赋postgresql系统变量,如now(),直接像上面这样写就可以了
如果字段是数值型,要让它进行计算,直接像上面这样写也行,可以是多个字段用加号连起来。当然你也可以将字段时读出来进行计算后再赋值提交也没有问题
具体操作需要大家自己多debug,多测试使用才知道怎么应用到真实项目中。
版权声明:本文原创发表于 博客园,作者为 AllEmpty 本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。
python开发QQ群:669058475(本群已满)、733466321(可以加2群) 作者博客:http://www.cnblogs.com/EmptyFS/
我的第一个python web开发框架(33)——接口代码重构的更多相关文章
- 我的第一个python web开发框架(41)——总结
我的第一个python web开发框架系列博文从17年6.7月份开始写(存了近十章稿留到9月份才开始发布),到今天结束,一年多时间,想想真不容易啊. 整个过程断断续续,中间有段时间由于工作繁忙停了好长 ...
- 我的第一个python web开发框架(14)——后台管理系统登录功能
接下来正式进入网站的功能开发.要完成后台管理系统登录功能,通过查看登录页面,我们可以了解到,我们需要编写验证码图片获取接口和登录处理接口,然后在登录页面的HTML上编写AJAX. 在进行接口开发之前, ...
- 我的第一个python web开发框架(21)——小结
这个小网站终于成功上线,小白除了收获一笔不多的费用外,还得到女神小美的赞赏,心中满满的成就感.这一天下班后,他请老菜一起下馆子,兑现请吃饭的承诺,顺便让老菜点评一下. 小白:老大,在你的指导下终于完成 ...
- 我的第一个python web开发框架(1)——前言
由于之前经验不是很丰富,写的C#系统太过复杂,所以一直想重写,但学的越多越觉得自己懂的越少,越觉的底气不足.所以一直不敢动手,在内心深处对自己讲,要静下心来认真学习,继续沉淀沉淀.这两年多以来找各种机 ...
- 我的第一个python web开发框架(3)——怎么开始?
小白与小美公司经过几次接触商谈,好不容易将外包签订了下来,准备开始大干一场.不过小白由于没有太多的项目经验,学过python懂得python的基本语法,在公司跟着大家做过简单功能,另外还会一些HTML ...
- 我的第一个python web开发框架(22)——一个安全小事故
在周末的一个早上,小白还在做着美梦,就收到了小美的连环追魂call,电话一直响个不停. 小白打着哈欠拿起电话:早上好美女. 小美:出事了出事了,我们公司网站一早访问是一片空白,什么内容都没有了,你赶急 ...
- 我的第一个python web开发框架(15)——公司介绍编辑功能
完成登录以后,就会进入后台管理系统的主界面,因为这个是小项目,所以导航菜单全部固化在HTML中,不能修改.一般后台还会有一个欢迎页或关键数据展示的主页面,小项目也没有多大的必要,所以登录后直接进入公司 ...
- 我的第一个python web开发框架(16)——产品分类管理
产品分类管理的html页面之前忘记做了,这次附件里补上. 好了先上图 从页面效果图来看,我们需要开发列表获取接口.添加接口.单条记录获取接口.编辑接口和删除接口 对于产品分类列表,我们将使用jqgri ...
- 我的第一个python web开发框架(40)——后台日志与异常处理
后台权限和底层框架的改造终于完成了,小白也终于可以放下紧悬着的心,可以轻松一下了.这不他为了感谢老菜,又找老菜聊了起来. 小白:多谢老大的帮忙,系统终于改造完成了,可以好好放松一下了. 老菜:呵呵,对 ...
随机推荐
- Leetcode - 剑指offer 面试题29:数组中出现次数超过一半的数字及其变形(腾讯2015秋招 编程题4)
剑指offer 面试题29:数组中出现次数超过一半的数字 提交网址: http://www.nowcoder.com/practice/e8a1b01a2df14cb2b228b30ee6a92163 ...
- Zookeeper~Linux环境下的部署
介绍 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的软件,提 ...
- CPU的load和使用率傻傻分不清
1. 什么是Cpu的Load 使用uptime.top或者查看/proc/loadavg都可以看到CPU的load统计,这里有三个值,分别代表1分钟.5分钟和15分钟的CPU Load情况.大部分人认 ...
- Chapter 5 Blood Type——4
"Does he mean you?" Jessica asked with insulting astonishment in her voice. “他对你有意思吗?”Jess ...
- 文本主题模型之潜在语义索引(LSI)
在文本挖掘中,主题模型是比较特殊的一块,它的思想不同于我们常用的机器学习算法,因此这里我们需要专门来总结文本主题模型的算法.本文关注于潜在语义索引算法(LSI)的原理. 1. 文本主题模型的问题特点 ...
- 什么是LogDashboard?
What is LogDashboard 接上篇 LogDashboard是可视化的日志面板,摆脱了传统查看txt与数据库的方式. 使查看日志变的简单方便并且可供分析 基于Net Core中间件编写适 ...
- web进修之—Hibernate 关系映射(3)
概述 Hibernate的关系映射是Hibernate使用的难点或者是重点(别担心,不考试哦~),按照不同的分类方式可以对这些映射关系做一个分类,如: 按对象对应关系分: 一对一 多对一/一对多 多对 ...
- springmvc 项目完整示例05 日志 --log4j整合 配置 log4j属性设置 log4j 配置文件 log4j应用
log4j 就是log for java嘛,老外都喜欢这样子,比如那个I18n ---internationalization 不就是i和n之间有18个字母... http://logging.a ...
- Jenkins结合.net平台之ftp客户端
上一节我们讲解了如何配置ftp服务端,本节我们讲解如何使用winscp搭建ftp客户端,为什么使用winscp而不是filezilla客户端版,前面我们简单说过,这里不再赘述. 下载winscp以后我 ...
- Centos7破解密码的两种方法--技术流ken
Centos7忘记密码 在工作或者自己练习的时候我们难免会大意忘掉自己的root密码,有些同学忘掉密码竟然第一选择是重装系统,工作中可万万使不得! 本篇博客将讲解两种最常用的破解centos7忘掉 ...