我的第一个python web开发框架(29)——定制ORM(

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

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

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

  先上产品新增接口代码

 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, "提交失败")
 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, "提交失败")

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

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

  操作步骤:

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

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

  操作步骤如下几步:

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

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

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

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

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

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

 

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

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

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

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

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

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

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

key_list = []
value_list = []
for key in fields.keys():
    key_list.append(key)
    value_list.append('%(' + key + ')s')
# 拼接字段与值
field_list = [key + ' = %(' + key + ')s' for key in fields.keys()]

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

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

key_list = ['name', 'product_class_id', 'code']
value_list = ['%(name)s', '%(product_class_id)s', '%(code)s']
field_list = []
for key in fields.keys():
    field_list.append(key + ' = %(' + key + ')s')

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

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

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

  执行完后,field_list的值为:

  执行后生成的值为:

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

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

  然后将它们与新增sql合成

# 设置sql拼接字典
parameter = {
    'table_name': self.__table_name,
    'field_list': ','.join(field_list)
}
sql = "insert into %(table_name)s (%(key_list)s) values (%(value_list)s) returning id " % parameter

  执行后生成的值为:

  执行后sql值为:

parameter = {'field_list': 'content = %(content)s,name = %(name)s', 'table_name': 'product'}
sql = 'insert into product (name,product_class_id,code) values (%(name)s,%(product_class_id)s,%(code)s) '

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

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

# 如果存在更新条件,则将条件添加到sql拼接更换字典中
if wheres:
    parameter['wheres'] = ' where ' + wheres
else:
    parameter['wheres'] = ''
sql = sql % fields

  执行后parameter值为:

  生成最终可执行的sql语句

parameter = {'wheres': ' where id=2', 'field_list': 'content = %(content)s,name = %(name)s', 'table_name': 'product'}
sql = "insert into product (name,product_class_id,code) values ('名称',1,'201808031245678') "

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

 

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

  完整代码

本文由金沙官网线上发布于编程,转载请注明出处:我的第一个python web开发框架(29)——定制ORM(

您可能还会对下面的文章感兴趣: