我的第一个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)——后台日志与异常处理
后台权限和底层框架的改造终于完成了,小白也终于可以放下紧悬着的心,可以轻松一下了.这不他为了感谢老菜,又找老菜聊了起来. 小白:多谢老大的帮忙,系统终于改造完成了,可以好好放松一下了. 老菜:呵呵,对 ...
随机推荐
- Java String:重要到别人只能当老二的字符串类
字符串,是Java中最重要的类.这句肯定的推断不是Java之父詹姆斯·高斯林说的,而是沉默王二说的,因此你不必怀疑它的准确性. 关于字符串,有很多的面试题,但我总觉得理论知识绕来绕去没多大意思.你比如 ...
- 【Maven】---坐标与依赖
Maven坐标与依赖 最近想深度学习下maven,找到一本书叫<Maven实战>,这本书讲的确实很好,唯一遗憾的是当时maven教学版本是3.0.0的,而目前已经到了3.5.4了,版本存在 ...
- Django2.1.2创建默认管理后台
1.在app的models.py中添加以下代码: from django.db import models # Create your models here. # Register your mod ...
- linux-centerOs6.8安装nginx与配置
一:安装nginx 1.安装gcc(命令:yum install gcc)备注:可以输入gcc -v查询版本信息,查看是否自带安装 2.安装pcre(命令:yum install pcre-devel ...
- redis 系列17 持久化 AOF
一.概述 除了上篇介绍的RDB持久化功能之外,Redis还提供了AOF(Append Only File)持久化功能.与RDB保存数据库中的键值对来记录数据库状态不同,AOF是通过保存redis服务器 ...
- C#版 - PAT乙级(Basic Level)真题 之 1024.科学计数法转化为普通数字 - 题解
版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. PAT Bas ...
- 【朝花夕拾】Android性能篇之(四)Apk打包
前言 APK,即Android Package,是将android程序和资源整合在一起,形成的一个.apk文件.相信所有的Android程序员是在IDE的帮助下,完成打包轻而易举,但对打包流程真正清楚 ...
- Kestrel.Transport.Sockets分析与使用
相信大家都清楚asp core有着非常出色的性能,它出色的性能也源于网络服务模块Kestrel:在techempower测试中Kestrel基础核心达到了700万级别的RPS吞吐能力,具备这样的能力那 ...
- RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.2->Web版本新增新的角色授权管理界面效率更高、更规范
角色授权管理模块主要是对角色的相应权限进行集中设置.在角色权限管理模块中,管理员可以添加或移除指定角色所包含的用户.可以分配或授予指定角色的模块(菜单)的访问权限.可以收回或分配指定角色的操作(功能) ...
- 离线批量数据通道Tunnel的最佳实践及常见问题
基本介绍及应用场景 Tunnel是MaxCompute提供的离线批量数据通道服务,主要提供大批量离线数据上传和下载,仅提供每次批量大于等于64MB数据的场景,小批量流式数据场景请使用DataHub实时 ...