彩世界开奖app官网-彩世界平台官方网址(彩票平台)
做最好的网站
来自 计算机编程 2019-12-07 01:40 的文章
当前位置: 彩世界开奖app官网 > 计算机编程 > 正文

自己的第多个python web开荒框架(33)——接口代

 1 @put('/api/product/<id:int>/')
 2 def callback(id):
 3     """
 4     修改记录
 5     """
 6     name = web_helper.get_form('name', '产品名称')
 7     code = web_helper.get_form('code', '产品编码')
 8     product_class_id = convert_helper.to_int0(web_helper.get_form('product_class_id', '产品分类'))
 9     standard = web_helper.get_form('standard', '产品规格')
10     quality_guarantee_period = web_helper.get_form('quality_guarantee_period', '保质期')
11     place_of_origin = web_helper.get_form('place_of_origin', '产地')
12     front_cover_img = web_helper.get_form('front_cover_img', '封面图片')
13     content = web_helper.get_form('content', '产品描述', is_check_special_char=False)
14     # 防sql注入攻击处理
15     content = string_helper.filter_str(content, "'")
16     # 防xss攻击处理
17     content = string_helper.clear_xss(content)
18     is_enable = convert_helper.to_int0(web_helper.get_form('is_enable', '是否启用'))
19 
20     # 设置新增参数
21     fields = {
22         'name': string(name),
23         'code': string(code),
24         'product_class_id': product_class_id,
25         'standard': string(standard),
26         'quality_guarantee_period': string(quality_guarantee_period),
27         'place_of_origin': string(place_of_origin),
28         'front_cover_img': string(front_cover_img),
29         'content': string(content),
30         'is_enable': is_enable,
31     }
32     # 实例化product表操作类ProductLogic
33     _product_logic = product_logic.ProductLogic()
34     # 修改记录
35     result = _product_logic.edit_model(id, fields)
36     # 判断是否提交成功
37     if result:
38         return web_helper.return_msg(0, '成功')
39     else:
40         return web_helper.return_msg(-1, "提交失败")

  在数据库操作时,新增记录也是必不可少的,接下来我们应用字典的特性来组合sql语句

1     ##############################################################
2     ### 获取登录用户记录,并进行登录验证 ###
3     ##############################################################
4     sql = """select * from manager where login_name='%s'""" % (username,)
5     # 从数据库中读取用户信息
6     manager_result = db_helper.read(sql)
7     # 判断用户记录是否存在
8     if not manager_result:
9         return web_helper.return_msg(-1, '账户不存在')

  第21行到25行,是我们常用修改记录的sql语句,它与插入记录差别比较大,但也有相似的地方,那就是都是字段与值一一对应,我们同样可以使用字典的方式将它做为ORM的参数值,在ORM中进行转换处理,组合成对应的sql语句。

  3.在进行下一步之前,大家首先要了解python字符串替的有多种方法,例如:方法一:’Hello %s' % ('world',)  ;方法二:'Hello %(name)s' % {'name': 'world'} ;等,还有很多其他方法这里不一一列举。第一种只能按照指定的顺序进行替换,数量必须一致,不然会出错;而第二种字典类型替换时,字典位置不需要考虑,字典值超出替换内容,会自动忽略,它最大的好处,我觉得是可读性,让这个字符串变的更加容易理解。所以下面我们将会使用字典替换方法。

 

  最后将它与最开始提交的字典参数进行合成

  最后将它与最开始提交的字典参数进行合成

  只需要将第7行到第10行替换对应的调用代码就可以了

  然后将它们与编辑sql合成

  操作步骤如下几步:

  首先是初始化产品逻辑层操作类,然后调用delete_model()这个方法就可以了

  操作步骤:

 

 1     def get_model_for_cache_of_where(self, where):
 2         """
 3         通过条件获取记录实体————条件必须是额外的主键,也就是说记录是唯一的(我们经常需要使用key、编码或指定条件来获取记录,这时可以通过当前方法来获取)
 4         :param where: 查询条件
 5         :return: 记录实体
 6         """
 7         # 生成实体缓存key
 8         model_cache_key = self.__table_name   encrypt_helper.md5(where)
 9         # 通过条件从缓存中获取记录id
10         pk = cache_helper.get(model_cache_key)
11         # 如果主键id存在,则直接从缓存中读取记录
12         if pk:
13             return self.get_model_for_cache(pk)
14 
15         # 否则从数据库中获取
16         result = self.get_model(where)
17         if result:
18             # 存储条件对应的主键id值到缓存中
19             cache_helper.set(model_cache_key, result.get(self.__pk_name))
20             # 存储记录实体到缓存中
21             self.set_model_for_cache(result.get(self.__pk_name), result)
22             return result

  执行后sql值为:

  在python中,我们最常用的就是字典,从新增记录的语句中,可以看到字段与值是一一对应的,那么我们就可以考虑使用字典的方式来进行存储字段与值,在ORM中对其进行处理,然后拼接生成对应的sql语句。

  对于字段值,如果为字符串、具体时间、json等类型的,也就是说需要用单撇号括起来的,我们就需要调用string_helper模块的string方法进行转换,它可以为变量增加单撇号,如果直接赋字符串值,生成的sql语句是没有单撇号的,这里要注意一下

  有些朋友可能会奇怪,这里都知道主健了,为什么还要增加wheres条件呢?这是因为,我们在更新一些记录时,比如说更新订单,我们虽然知道订单的主键值,但这个订单并不一定就属于这个用户的,或者是该订单指定状态才能进行相关的操作,否则不能修改,这时我们就可以直接添加条件值来进行更新,如果条件不成立时则更新失败

sql = "insert into %(table_name)s (%(key_list)s) values (%(value_list)s) returning id " % parameter

  我们在开发时,除了通过主键id来获取记录实体以外,在有的数据表中,还会存在第二个主键,或多个主键的情况,我们需要通过这些主键来获取对应的记录实休,比如说管理员或用户表中的登录账号字段;订单表中的订单编码字段等。

  代码出来了,我们直接上单元测试跑一下看看效果吧

  例如,我们需要添加产品名称、产品编码、产品分类id,可以它们用字典存储起来做为参数

 1 @delete('/api/product/<id:int>/')
 2 def callback(id):
 3     """
 4     删除指定记录
 5     """
 6     # 编辑记录
 7     sql = """delete from product where id=%s returning id"""
 8     vars = (id,)
 9     # 写入数据库
10     result = db_helper.write(sql, vars)
11     # 判断是否提交成功
12     if result:
13         return web_helper.return_msg(0, '成功')
14     else:
15         return web_helper.return_msg(-1, "删除失败")

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

 

  我们可以更改为:

  对于通过主键id修改记录的操作,我们也是最常用的,所以我们可以增加一个通过主键值来修改记录的方法,可以在写参数时少写一个参数

------ini------
{'content': '产品描述', 'name': '饼干', 'place_of_origin': '广东广州', 'add_time': datetime.datetime(2018, 7, 25, 23, 10, 4), 'code': '20180212321211', 'is_enable': 1, 'front_cover_img': 'http://xxx.com/xxx.jpg', 'product_class_id': 1, 'quality_guarantee_period': '2018年12月', 'id': 2, 'standard': '500g'}
{'content': '', 'name': '名称', 'place_of_origin': '', 'add_time': datetime.datetime(2018, 8, 3, 16, 51, 3), 'code': '201808031245678', 'is_enable': 0, 'front_cover_img': '', 'product_class_id': 1, 'quality_guarantee_period': '', 'id': 15, 'standard': ''}
------clear------

  如果是数值类型,直接写值就可以了,当然直接赋字符串值也没有关系,因为生成sql是不会自动添加单撇号的

  生成最终可执行的sql语句

 

1     ##############################################################
2     ### 获取登录用户记录,并进行登录验证 ###
3     ##############################################################
4     _manager_logic = manager_logic.ManagerLogic()
5     # 从数据库中读取用户信息
6     manager_result = _manager_logic.get_model_for_cache_of_where('login_name='   string(username))
7     # 判断用户记录是否存在
8     if not manager_result:
9         return web_helper.return_msg(-1, '账户不存在')
# 如果存在更新条件,则将条件添加到sql拼接更换字典中
if wheres:
    parameter['wheres'] = ' where '   wheres
else:
    parameter['wheres'] = ''
 1 @post('/api/product/')
 2 def callback():
 3     """
 4     新增记录
 5     """
 6     name = web_helper.get_form('name', '产品名称')
 7     code = web_helper.get_form('code', '产品编码')
 8     product_class_id = convert_helper.to_int0(web_helper.get_form('product_class_id', '产品分类'))
 9     standard = web_helper.get_form('standard', '产品规格')
10     quality_guarantee_period = web_helper.get_form('quality_guarantee_period', '保质期')
11     place_of_origin = web_helper.get_form('place_of_origin', '产地')
12     front_cover_img = web_helper.get_form('front_cover_img', '封面图片')
13     content = web_helper.get_form('content', '产品描述', is_check_special_char=False)
14     # 防sql注入攻击处理
15     content = string_helper.filter_str(content, "'")
16     # 防xss攻击处理
17     content = string_helper.clear_xss(content)
18     is_enable = convert_helper.to_int0(web_helper.get_form('is_enable', '是否启用'))
19 
20     # 添加记录(使用returning这个函数能返回指定的字段值,这里要求返回新添加记录的自增id值)
21     sql = """insert into product (name, code, product_class_id, standard, quality_guarantee_period,
22                 place_of_origin, front_cover_img, content, is_enable)
23               values (%s, %s, %s, %s, %s, %s, %s, %s, %s) returning id"""
24     vars = (name, code, product_class_id, standard, quality_guarantee_period, place_of_origin, front_cover_img, content, is_enable)
25     # 写入数据库
26     result = db_helper.write(sql, vars)
27     # 判断是否提交成功
28     if result and result[0].get('id'):
29         return web_helper.return_msg(0, '成功')
30     else:
31         return web_helper.return_msg(-1, "提交失败")

 

parameter = {'field_list': 'content = %(content)s,name = %(name)s', 'table_name': 'product'}
key_list = ['name', 'product_class_id', 'code']
value_list = ['%(name)s', '%(product_class_id)s', '%(code)s']

  正常情况下,我们直接通过get_model()方法就可以读取对应的记录了,如果我们想减少数据库的查询,直接在缓存中如何使用呢?直接存取记录实体,由于这些额外的主键并没有与ORM中的编辑与删除操作关联,即在进行编辑与删除操作时不会同步更新用其他主键存储的实体内容,这样就会产生脏数据。所以我们可以换一种思路来实现,我们可以将这些额外的主键和对应的值生成缓存组合key,里面存储对应的记录实体id,也就是说在存储记录实体时,还是使用原来的主键id存储该实体,然后用额外主键和对应值生成缓存组合key中存储主键id,在获取记录实体时,先用这个组合key提取对应的id,再用这个id来获取记录实体。这个说明好像有点绕,大家自己debug一下就很容易明白其中的原理了,下面看代码:

  for循环是python中应用最多的语句之一,它通过可以将很复杂的需要很多代码才能实现的语句,用一行语句将它实现出来,如果你能熟练掌握,你会发现它不但能简化代码,同时也提高了代码的可读性。

  然后可以通过for循环,将字典参数进行处理,提取出来存储到list中

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

   大家自己多debug一下,就很容易理解这个模块是怎么生成sql的

 

  产品分类的删除分类接口大家会看到它的代码与产品删除接口差不多,不过多了一个该分类是否已经被引用的一个判断,对于这个下面专门说明一下

  完整代码

sql = sql % fields

  如果要赋postgresql系统变量,如now(),直接像上面这样写就可以了

#!/usr/bin/evn python
# coding=utf-8

import unittest
from common.string_helper import string
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()
        # 测试编辑记录
        fields = {
            'name': "'产品名称'",
            'content': "'产品详情'",
        }
        result = _product_logic.edit(fields, 'id=2', 'product_class_id')
        print(result)

        ##############################################

if __name__ == '__main__':
    unittest.main()
key_list = []
value_list = []
for key in fields.keys():
    key_list.append(key)
    value_list.append('%('   key   ')s')

 

"update product set content = '产品详情',name = '产品名称'  where id=2 returning id , product_class_id"

  生成最终可执行的sql语句

 1 @delete('/api/product_class/<id:int>/')
 2 def callback(id):
 3     """
 4     删除指定记录
 5     """
 6     # 判断该分类是否已经被引用,是的话不能直接删除
 7     sql = """select count(*) as total from product where product_class_id=%s""" % (id,)
 8     # 读取记录
 9     result = db_helper.read(sql)
10     if result and result[0].get('total', -1) > 0:
11         return web_helper.return_msg(-1, "该分类已被引用,请清除对该分类的绑定后再来删除")
12 
13     # 编辑记录
14     sql = """delete from product_class where id=%s returning id"""
15     vars = (id,)
16     # 写入数据库
17     result = db_helper.write(sql, vars)
18     # 判断是否提交成功
19     if result:
20         return web_helper.return_msg(0, '成功')
21     else:
22         return web_helper.return_msg(-1, "删除失败")

  执行后parameter值为:

  执行后sql值为:

  这段代码后半部分可以参考产品的删除接口实现,前半部分需要调用产品方法进行判断处理。

  在执行更新操作时,我们也经常会指定返回记录的字段值回来使用。比如说:我们要更新id为2的记录,将它设置为禁用状态,然后需要同步更新该分类记录的产品数量,正常来说我们需要执行修改操作以后,还需要将记录查询出来,然后获取它的分类id,然后再去更新该分类的产品数量,而postgresql由于拥有returning,所以我们只需要将分类id放在returning语句中就可以了,执行更新操作后会将分类id同时返回回来给我们使用。

  然后我们设置一个sql字符串拼接字典,将表名、字段名字符串与值字符串存储进去,在存储前使用join方式进行拼接,生成用逗号分隔的字符串

  在写ORM模块时,我们已经对产品接口的分页查询、新增、修改、获取指定产品实体接口已经重构好了,还剩下删除接口未完成

field_list = ['content = %(content)s', 'name = %(name)s']

 

  前面ORM模块我们已经完成了开发,接下来要做的就是对项目代码进行重构了。因为对底层数据库操作模块(db_helper.py)进行了改造,之前项目的接口代码全都跑不起来了。

  输出结果:

sql = 'insert into product (name,product_class_id,code) values (%(name)s,%(product_class_id)s,%(code)s) '
 1     ##############################################################
 2     ### 更新用户信息到数据库 ###
 3     ##############################################################
 4     # 更新当前管理员最后登录时间、Ip与登录次数(字段说明,请看数据字典)
 5     fields = {
 6         'last_login_time': 'now()',
 7         'last_login_ip': string(ip),
 8         'login_count': 'login_count 1',
 9     }
10     # 写入数据库
11     _manager_logic.edit_model(manager_id, fields)
 1     def edit(self, fields, wheres='', returning=''):
 2         """批量编辑数据库记录"""
 3         ### 拼接sql语句 ###
 4         # 拼接字段与值
 5         field_list = [key   ' = %('   key   ')s' for key in fields.keys()]
 6         # 设置sql拼接字典
 7         parameter = {
 8             'table_name': self.__table_name,
 9             'field_list': ','.join(field_list)
10         }
11         # 如果存在更新条件,则将条件添加到sql拼接更换字典中
12         if wheres:
13             parameter['wheres'] = ' where '   wheres
14         else:
15             parameter['wheres'] = ''
16 
17         # 如果有指定返回参数,则添加
18         if returning:
19             parameter['returning'] = ', '   returning
20         else:
21             parameter['returning'] = ''
22 
23         # 生成sql语句
24         sql = "update %(table_name)s set %(field_list)s %(wheres)s returning id %(returning)s" % parameter
25         sql = sql % fields
26 
27         return self.execute(sql)

  写到这里,可以看到查询与执行,都使用类似的with方法,我们可以将它们提取出来重构成独立的函数,为后续的修改和其他查询去除重复代码,改造后代码如下:

 

sql = sql % fields
parameter = {
    'table_name': self.__table_name,
    'key_list': ','.join(key_list),
    'value_list': ','.join(value_list)
}

 

 

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

  如果字段是数值型,要让它进行计算,直接像上面这样写也行,可以是多个字段用加号连起来。当然你也可以将字段时读出来进行计算后再赋值提交也没有问题

# 拼接字段与值
field_list = [key   ' = %('   key   ')s' for key in fields.keys()]
sql = "insert into product (name,product_class_id,code) values ('名称',1,'201808031245678') "

  当你习惯这种写法以后,你会发现实现各个接口会变得非常的简单与方便,开发速度比之前也提升了很多

 

  PS:单元测试中,通过from common.string_helper import string导入了string这个方法,它是用来给字符串添加单撇号字符(')用的,因为在更新数据库时,字符串类型需要用单撇号括起来的,而Python中直接使用单撇字符只是标识它为字符串而已,需要用'或双引号 单撇字符 双引号方式,才能得到我们想要的结果,为了方便操作,所以增加了string这个方法,帮我们进行转换。

  2.该功能是否是常用的功能,能否封装成公共方法,如果可以就将它封装到逻辑层基类(ORM模块)中去,让所有继承的子类都拥有这个功能

 

  这里的sql语句额外添加了postgresql的returning函数,在默认情况下会返回数据插入成功后的主键值给主程序。我们在进行新增操作时,经常要获取新增记录的自增id,通过return id就可以将它返回给我们,如果你还需要返回其他字段值,可以在这个新增方式的returning参数中添加想要返回的字段名,如果想返回整条记录,输入*号就可以了。

python开发QQ群:669058475    作者博客:

  我们同样使用for循环,遍历所有字典内容,将它们提取出来进行组合。可能有朋友对上面这个for语句不太理解,我将它分解一下

  执行后,key_list与value_list的值分别为:

  还有登录接口最底部,更新管理员最后登录时、登录ip和累加登录次数需要改造,具体代码如下:

parameter = {'wheres': ' where id=2', 'field_list': 'content = %(content)s,name = %(name)s', 'table_name': 'product'}

  4.新增记录方法接收到参数以后,使用for循环,将字段名提取出来,生成sql插入字段名数组和字典替换数组,即:insert into table_name (字段名,字段名...) values (值,值...),这里需要将字典中的字段名提取出来组合成“字段名,字段名...”这样的串,值也是一样,为了让组合后的字符串更容易调试与理解,我们将它生成字典替换格式%(name1)s,%(name2)s...,最好再使用字典直接替换(当然你直接将值连接起来也行,你可以根据自己的需要进行调整)。

  产品分类相关接口(product_class.py)与产品相关接口(product.py)功能差不多,具体实现我就不一一讲解了,大家可以自己试试

  由于是编辑记录,所以我们通常要指定编辑记录的条件,比如编辑id=1的记录,或者更新所有记录,这时就不需要指定条件,所以我们还需要添加条件进来

  1.将新增记录时的字段名与值,使用字典方式存储起来

  1.有没有替代可以实现的方法存在

  然后可以通过for循环,将字典参数进行处理,提取出来存储到list中

  2.将字典做为参数传给ORM新增记录方法

  3.如果它只是对指定表单操作时才用到,就将它封装到该逻辑层子类,方便该子类要用到时可以随时调用

# 如果有指定返回参数,则添加
if returning:
    parameter['returning'] = ', '   returning
else:
    parameter['returning'] = ''

  输出结果:

    def exists(self, wheres):
        """检查指定条件的记录是否存在"""
        return self.get_count(wheres) > 0
parameter = {'wheres': ' where id=2', 'field_list': 'content = %(content)s,name = %(name)s', 'table_name': 'product', 'returning': ', product_class_id'}

 

  如果前面代码有认真学习的小伙伴看到这段代码,要改成ORM方式应该很容易实现了

  同样的,我们看看产品记录编辑的例子,方便进行理解

python开发QQ群:669058475    作者博客:

  在编写时我们会发现,我们的ORM并没有直接判断记录是否存在的方法,只有一个用于获取指定条件记录数的方法。

  接下来我们要封装的是修改记录模块。

  前面的接口也可以改造为

 1 @delete('/api/product_class/<id:int>/')
 2 def callback(id):
 3     """
 4     删除指定记录
 5     """
 6     # 实例化product表操作类ProductLogic
 7     _product_logic = product_logic.ProductLogic()
 8     # 判断该分类是否已经被引用,是的话不能直接删除
 9     if _product_logic.exists('product_class_id='   str(id)):
10         return web_helper.return_msg(-1, "该分类已被引用,请清除对该分类的绑定后再来删除")
11 
12     # 实例化product_class表操作类product_class_logic
13     _product_class_logic = product_class_logic.ProductClassLogic()
14     result = _product_class_logic.delete_model(id)
15     # 判断是否提交成功
16     if result:
17         return web_helper.return_msg(0, '成功')
18     else:
19         return web_helper.return_msg(-1, "删除失败")

  先上产品信息编辑接口代码

  然后将它们与新增sql合成

  一般来说,我们在开发时发现ORM没有自己想要的方法时,我们需要做以下思考:

 

  执行后生成的值为:

  我们可以改造为:

python开发QQ群:669058475    作者博客:

  代码行数比之前是增加了,但可读性好了很多

  下面改造调用例子(请查看login.py第35行附近)

  然后我们设置一个sql字符串拼接字典,将表名、字段名字符串与值字符串存储进去,在存储前使用join方式进行拼接,生成用逗号分隔的字符串

#!/usr/bin/evn python
# coding=utf-8

import unittest
from common.string_helper import string
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)

        # 测试新增记录
        fields = {
            'name': string('名称'),
            'code': string('201808031245678'),
            'product_class_id': 1,
        }
        result = _product_logic.add_model(fields, '*')
        print(result)

        ##############################################

if __name__ == '__main__':
    unittest.main()

  这段代码的要求是判断指定的分类是否被产品引用,抽象出来的意思就是判断指定条件的记录是否存在,对于这个功能有开发经验的小伙伴很容易判断它是很多地方都有可能要用到的通用方法,所以我们需要在ORM中增加一下这个方法。而我们ORM已经存在get_count()这个获取记录数的方法存在了,我们可以通过调用这个方法来判断记录数量是否大于0,来得出指定条件的记录是否存在这样的结果。

  1.将新增记录时的字段名与值,使用字典方式存储起来

  在21行到24行就是sql语句的拼接,使用这种方法,我们经常会因为多写或少写%s和变量,导致sql执行出错。

 

# 设置sql拼接字典
parameter = {
    'table_name': self.__table_name,
    'field_list': ','.join(field_list)
}
 1 @post('/api/product/')
 2 def callback():
 3     """
 4     新增记录
 5     """
 6     name = web_helper.get_form('name', '产品名称')
 7     code = web_helper.get_form('code', '产品编码')
 8     product_class_id = convert_helper.to_int0(web_helper.get_form('product_class_id', '产品分类'))
 9     standard = web_helper.get_form('standard', '产品规格')
10     quality_guarantee_period = web_helper.get_form('quality_guarantee_period', '保质期')
11     place_of_origin = web_helper.get_form('place_of_origin', '产地')
12     front_cover_img = web_helper.get_form('front_cover_img', '封面图片')
13     content = web_helper.get_form('content', '产品描述', is_check_special_char=False)
14     # 防sql注入攻击处理
15     content = string_helper.filter_str(content, "'")
16     # 防xss攻击处理
17     content = string_helper.clear_xss(content)
18     is_enable = convert_helper.to_int0(web_helper.get_form('is_enable', '是否启用'))
19 
20     # 设置新增参数
21     fields = {
22         'name': string(name),
23         'code': string(code),
24         'product_class_id': product_class_id,
25         'standard': string(standard),
26         'quality_guarantee_period': string(quality_guarantee_period),
27         'place_of_origin': string(place_of_origin),
28         'front_cover_img': string(front_cover_img),
29         'content': string(content),
30         'is_enable': is_enable,
31     }
32     # 实例化product表操作类ProductLogic
33     _product_logic = product_logic.ProductLogic()
34     # 新增记录
35     result = _product_logic.add_model(fields)
36     # 判断是否提交成功
37     if result:
38         return web_helper.return_msg(0, '成功')
39     else:
40         return web_helper.return_msg(-1, "提交失败")
1 ##############################################################
2     ### 更新用户信息到数据库 ###
3     ##############################################################
4     # 更新当前管理员最后登录时间、Ip与登录次数(字段说明,请看数据字典)
5     sql = """update manager set last_login_time=%s, last_login_ip=%s, login_count=login_count 1 where id=%s"""
6     # 组合更新值
7     vars = ('now()', ip, manager_id,)
8     # 写入数据库
9     db_helper.write(sql, vars)
'update product set content = %(content)s,name = %(name)s  where id=1 returning id , product_class_id'

  代码大家多debug一下,就可以查看到每一行代码的执行情况以及sql拼接生成情况了。

  本文对应的源码下载

  2.将字典做为参数传给ORM编辑记录方法

  上单元测试代码:

 1 @delete('/api/product/<id:int>/')
 2 def callback(id):
 3     """
 4     删除指定记录
 5     """
 6     # 实例化product表操作类ProductLogic
 7     _product_logic = product_logic.ProductLogic()
 8     result = _product_logic.delete_model(id)
 9     # 判断是否提交成功
10     if result:
11         return web_helper.return_msg(0, '成功')
12     else:
13         return web_helper.return_msg(-1, "删除失败")
field_list = []
for key in fields.keys():
    field_list.append(key   ' = %('   key   ')s')
parameter = {'key_list': 'name,product_class_id,code', 'value_list': '%(name)s,%(product_class_id)s,%(code)s', 'table_name': 'product'}

  通过这个例子,大家在实际开发过程中,可以灵活的根据自己需要,来增加或改造对应的底层方法,积累你自己的底层框架代码,那么随着开发时间的增加,你开发起各种功能来就会越加得心应手了。

    def edit_model(self, pk, fields, wheres='', returning=''):
        """编辑单条数据库记录"""
        if not pk:
            return {}
        elif wheres:
            wheres = self.__pk_name   ' = '   str(id)   ' and '   wheres
        else:
            wheres = self.__pk_name   ' = '   str(id)

        return self.edit(fields, wheres, returning)
 1     def add_model(self, fields, returning=''):
 2         """新增数据库记录"""
 3         ### 拼接sql语句 ###
 4         # 初始化变量
 5         key_list = []
 6         value_list = []
 7         # 将传入的字典参数进行处理,把字段名生成sql插入字段名数组和字典替换数组
 8         # PS:字符串使用字典替换参数时,格式是%(name)s,这里会生成对应的字串
 9         # 比如:
10         #   传入的字典为: {'id': 1, 'name': '名称'}
11         #   那么生成的key_list为:'id','name'
12         #   而value_list为:'%(id)s,%(name)s'
13         #   最终而value_list为字符串对应名称位置会被替换成相应的值
14         for key in fields.keys():
15             key_list.append(key)
16             value_list.append('%('   key   ')s')
17         # 设置sql拼接字典,并将数组(lit)使用join方式进行拼接,生成用逗号分隔的字符串
18         parameter = {
19             'table_name': self.__table_name,
20             'pk_name': self.__pk_name,
21             'key_list': ','.join(key_list),
22             'value_list': ','.join(value_list)
23         }
24         # 如果有指定返回参数,则添加
25         if returning:
26             parameter['returning'] = ', '   returning
27         else:
28             parameter['returning'] = ''
29 
30         # 生成可以使用字典替换的字符串
31         sql = "insert into %(table_name)s (%(key_list)s) values (%(value_list)s) returning %(pk_name)s %(returning)s" % parameter
32         # 将生成好的字符串替字典参数值,生成最终可执行的sql语句
33         sql = sql % fields
34 
35         with db_helper.PgHelper(self.__db, self.__is_output_sql) as db:
36             # 执行sql语句
37             result = db.execute(sql)
38             if result:
39                 db.commit()
40                 return result[0]
41             return {}

  具体操作需要大家自己多debug,多测试使用才知道怎么应用到真实项目中。

  执行后生成的值为:

fields = {
    'name': "'名称'",
    'code': "'201808031245678'",
    'product_class_id': 1,
}

  细心的朋友会发现,ORM模块的缓存部分,多了一个get_model_for_cache_of_where()方法,下面我来说明一下它的用途。

  执行后parameter值为:

  先上产品新增接口代码

  有了这个方法,我们就可以继续对产品分类删除接口进行改造了

  这个步骤看起来跟新增记录差不多,只是生成sql的结果不一样而已。

  1 #!/usr/bin/env python
  2 # coding=utf-8
  3 
  4 from common import db_helper
  5 
  6 
  7 class LogicBase():
  8     """逻辑层基础类"""
  9 
 10     def __init__(self, db, is_output_sql, table_name, column_name_list='*', pk_name='id'):
 11         """类初始化"""
 12         # 数据库参数
 13         self.__db = db
 14         # 是否输出执行的Sql语句到日志中
 15         self.__is_output_sql = is_output_sql
 16         # 表名称
 17         self.__table_name = str(table_name).lower()
 18         # 查询的列字段名称,*表示查询全部字段,多于1个字段时用逗号进行分隔,除了字段名外,也可以是表达式
 19         self.__column_name_list = str(column_name_list).lower()
 20         # 主健名称
 21         self.__pk_name = str(pk_name).lower()
 22 
 23     #####################################################################
 24     ### 执行Sql ###
 25 
 26     def get_model(self, wheres):
 27         """通过条件获取一条记录"""
 28         # 如果有条件,则自动添加where
 29         if wheres:
 30             wheres = ' where '   wheres
 31 
 32         # 合成sql语句
 33         sql = "select %(column_name_list)s from %(table_name)s %(wheres)s" % 
 34               {'column_name_list': self.__column_name_list, 'table_name': self.__table_name, 'wheres': wheres}
 35         # 初化化数据库链接
 36         result = self.select(sql)
 37         if result:
 38             return result[0]
 39         return {}
 40 
 41     def get_model_for_pk(self, pk, wheres=''):
 42         """通过主键值获取数据库记录实体"""
 43         if not pk:
 44             return {}
 45         # 组装查询条件
 46         wheres = '%s = %s' % (self.__pk_name, str(pk))
 47 
 48         return self.get_model(wheres)
 49 
 50     def add_model(self, fields, returning=''):
 51         """新增数据库记录"""
 52         ### 拼接sql语句 ###
 53         # 初始化变量
 54         key_list = []
 55         value_list = []
 56         # 将传入的字典参数进行处理,把字段名生成sql插入字段名数组和字典替换数组
 57         # PS:字符串使用字典替换参数时,格式是%(name)s,这里会生成对应的字串
 58         # 比如:
 59         #   传入的字典为: {'id': 1, 'name': '名称'}
 60         #   那么生成的key_list为:'id','name'
 61         #   而value_list为:'%(id)s,%(name)s'
 62         #   最终而value_list为字符串对应名称位置会被替换成相应的值
 63         for key in fields.keys():
 64             key_list.append(key)
 65             value_list.append('%('   key   ')s')
 66         # 设置sql拼接字典,并将数组(lit)使用join方式进行拼接,生成用逗号分隔的字符串
 67         parameter = {
 68             'table_name': self.__table_name,
 69             'pk_name': self.__pk_name,
 70             'key_list': ','.join(key_list),
 71             'value_list': ','.join(value_list)
 72         }
 73         # 如果有指定返回参数,则添加
 74         if returning:
 75             parameter['returning'] = ', '   returning
 76         else:
 77             parameter['returning'] = ''
 78 
 79         # 生成可以使用字典替换的字符串
 80         sql = "insert into %(table_name)s (%(key_list)s) values (%(value_list)s) returning %(pk_name)s %(returning)s" % parameter
 81         # 将生成好的字符串替字典参数值,生成最终可执行的sql语句
 82         sql = sql % fields
 83 
 84         result = self.execute(sql)
 85         if result:
 86             return result[0]
 87         return {}
 88 
 89     def select(self, sql):
 90         """执行sql查询语句(select)"""
 91         with db_helper.PgHelper(self.__db, self.__is_output_sql) as db:
 92             # 执行sql语句
 93             result = db.execute(sql)
 94             if not result:
 95                 result = []
 96         return result
 97 
 98     def execute(self, sql):
 99         """执行sql语句,并提交事务"""
100         with db_helper.PgHelper(self.__db, self.__is_output_sql) as db:
101             # 执行sql语句
102             result = db.execute(sql)
103             if result:
104                 db.commit()
105             else:
106                 result = []
107         return result
108 
109     #####################################################################
 1 @put('/api/product/<id:int>/')
 2 def callback(id):
 3     """
 4     修改记录
 5     """
 6     name = web_helper.get_form('name', '产品名称')
 7     code = web_helper.get_form('code', '产品编码')
 8     product_class_id = convert_helper.to_int0(web_helper.get_form('product_class_id', '产品分类'))
 9     standard = web_helper.get_form('standard', '产品规格')
10     quality_guarantee_period = web_helper.get_form('quality_guarantee_period', '保质期')
11     place_of_origin = web_helper.get_form('place_of_origin', '产地')
12     front_cover_img = web_helper.get_form('front_cover_img', '封面图片')
13     content = web_helper.get_form('content', '产品描述', is_check_special_char=False)
14     # 防sql注入攻击处理
15     content = string_helper.filter_str(content, "'")
16     # 防xss攻击处理
17     content = string_helper.clear_xss(content)
18     is_enable = convert_helper.to_int0(web_helper.get_form('is_enable', '是否启用'))
19 
20     # 组成编辑Sql
21     sql = """
22           update product
23             set name=%s, code=%s, product_class_id=%s, standard=%s, quality_guarantee_period=%s,
24                 place_of_origin=%s, front_cover_img=%s, content=%s, is_enable=%s
25           where id=%s returning id"""
26     vars = (name, code, product_class_id, standard, quality_guarantee_period, place_of_origin, front_cover_img, content, is_enable, id)
27     # 写入数据库
28     result = db_helper.write(sql, vars)
29     # 判断是否提交成功
30     if result and result[0].get('id'):
31         return web_helper.return_msg(0, '成功')
32     else:
33         return web_helper.return_msg(-1, "提交失败")

  完整代码

  3.编辑记录方法接收到参数以后,使用for循环,将字段名提取出来,生成sql编辑字段名、数组和字典替换数组,即:update table_name set 字段名=值,字段名=值... where 条件,这里需要将字典中的字段名提取出来组合成“字段名=值,字段名=值...”这样的串

 

  执行完后,field_list的值为:

  前面的接口我们也改造一下

fields = {
    'name': "'产品名称'",
    'content': "'产品详情'",
}

  例如:我们需要修改产品Id为2的记录,将它的名称和产品详情进行更改,我们可以将更改内容组合成一个字典

sql = "update %(table_name)s set %(field_list)s %(wheres)s returning id %(returning)s" % parameter
------ini------
[{'id': 2, 'product_class_id': 1}]
------clear------

 

本文由彩世界开奖app官网发布于计算机编程,转载请注明出处:自己的第多个python web开荒框架(33)——接口代

关键词: