zoukankan      html  css  js  c++  java
  • 我的第一个python web开发框架(17)——产品管理

      这是后台管理系统最后一个功能,产品管理,它的接口与页面功能与上一章差不多。

      获取产品列表接口

     1 @get('/api/product/')
     2 def callback():
     3     """
     4     获取列表数据
     5     """
     6     # 设置查询条件
     7     wheres = ''
     8     # 产品分类id
     9     product_class_id = convert_helper.to_int0(web_helper.get_query('product_class_id', '', is_check_null=False))
    10     if product_class_id > 0:
    11         wheres = 'where product_class_id=' + str(product_class_id)
    12     # 页面索引
    13     page_number = convert_helper.to_int1(web_helper.get_query('page', '', is_check_null=False))
    14     # 页面显示记录数量
    15     page_size = convert_helper.to_int0(web_helper.get_query('rows', '', is_check_null=False))
    16     # 排序字段
    17     sidx = web_helper.get_query('sidx', '', is_check_null=False)
    18     # 顺序还是倒序排序
    19     sord = web_helper.get_query('sord', '', is_check_null=False)
    20     # 初始化排序字段
    21     order_by = 'id desc'
    22     if sidx:
    23         order_by = sidx + ' ' + sord
    24 
    25     #############################################################
    26     # 初始化输出格式(前端使用jqgrid列表,需要指定输出格式)
    27     data = {
    28         'records': 0,
    29         'total': 0,
    30         'page': 1,
    31         'rows': [],
    32     }
    33     #############################################################
    34     # 执行sql,获取指定条件的记录总数量
    35     sql = 'select count(1) as records from product %(wheres)s' % {'wheres': wheres}
    36     result = db_helper.read(sql)
    37     # 如果查询失败或不存在指定条件记录,则直接返回初始值
    38     if not result or result[0]['records'] == 0:
    39         return data
    40     # 保存总记录数量
    41     data['records'] = result[0].get('records', 0)
    42 
    43     #############################################################
    44     ### 设置分页索引与页面大小 ###
    45     # 设置分页大小
    46     if page_size is None or page_size <= 0:
    47         page_size = 10
    48     # 计算总页数
    49     if data['records'] % page_size == 0:
    50         page_total = data['records'] // page_size
    51     else:
    52         page_total = data['records'] // page_size + 1
    53     # 记录总页面数量
    54     data['total'] = page_total
    55 
    56     # 判断提交的页码是否超出范围
    57     if page_number < 1 or page_number > page_total:
    58         page_number = page_total
    59     # 记录当前页面索引值
    60     data['page'] = page_number
    61 
    62     # 计算当前页面要显示的记录起始位置
    63     record_number = (page_number - 1) * page_size
    64     # 设置查询分页条件
    65     paging = ' limit ' + str(page_size) + ' offset ' + str(record_number)
    66     ### 设置排序 ###
    67     if not order_by:
    68         order_by = 'id desc'
    69     #############################################################
    70 
    71     # 组合sql查询语句
    72     sql = "select * from product %(wheres)s order by %(orderby)s %(paging)s" % 
    73            {'wheres': wheres, 'orderby': order_by, 'paging': paging}
    74     # 读取记录
    75     result = db_helper.read(sql)
    76     if result:
    77         # 存储记录
    78         data['rows'] = result
    79 
    80     if data:
    81         # 直接输出json
    82         return web_helper.return_raise(json.dumps(data, cls=json_helper.CJsonEncoder))
    83     else:
    84         return web_helper.return_msg(-1, "查询失败")
    View Code

      这个接口多了按产品分类id查询的条件,如果少了这个的话,直接将产品分类字段替换为产品字段变量就可以了。

      大家可以看到这里的代码好像有点复杂。是的,这里要进行分页查询进行了分页处理,所以代码有点多,不过写了很详细的注释,只要你对python的基本语法、字典的处理理解,然后对之前工具函数那里按要求重写过测试用例,那么对阅读这段代码是没有什么大问题的。

      下面再重新帮大家熟悉一下前面讲述过的工具函数

    product_class_id = convert_helper.to_int0(web_helper.get_query('product_class_id', '产品分类id', is_check_null=False))

      这是获取客户端(HTML)用AJAX提交上来的产品分类id接收处理,如果你认真看过前面工具函数内容的话,看到web_helper.get_query()这个函数应该会很熟悉,它就是获取GET方式提交值的接收函数,第一个参数是要接收的变量名称,第二个参数是这个变量的中文说明,第三个是在接收参数时,是否做非空判断,当前设置为这不是必填项。默认它为True,当为True时,如果客户端没有提交这个参数值,则系统自动会返回“xxx 不允许为空”,这个xxx就是第二个参数,也就是当前变量的中文说明,还有其他参数大家可以打看web_helper.py查看。

      convert_helper.to_int0()这个函数,在前面工具函数第一篇中讲到的函数,它会将接收到的参数字符串转为int类型值,如果这个参数小于0时,会自动使用默认值0代替。

    sql = 'select count(1) as records from product %(wheres)s' % {'wheres': wheres}

      使用习惯ORM的朋友可能会不太习惯直接写sql语句,本系列第一部分主要面向没有什么基础的朋友,所以尽量不封装各种类和函数,这样大家直接看到内容会更容易理解。第二部分会教大家自己简单封装一个ORM,到时重构后重复代码就会减少一大半。

      上面这行是获取当前查询有多少条记录的sql语句,熟悉python字符串替换的朋友应该会很熟悉,它会将字符串%后面的字典内容替代字符串中对应的键值,如果wheres值为空时,则替换空值,即将%(wheres)s这个键值替换掉。

      python的字符串替换有多种方式,而这里使用字典方式来替换会让代码可读性更高,而且字典中各个值的位置不需要按固定方式摆放,不容易出错。

      获取指定id的记录实体

     1 @get('/api/product/<id:int>/')
     2 def callback(id):
     3     """
     4     获取指定记录
     5     """
     6     sql = """select * from product where id = %s""" % (id,)
     7     # 读取记录
     8     result = db_helper.read(sql)
     9     if result:
    10         # 直接输出json
    11         return web_helper.return_msg(0, '成功', result[0])
    12     else:
    13         return web_helper.return_msg(-1, "查询失败")

      这段代码比较简单,第6行使用的就是%s替换字符串方式,后面的元组(id,)  好像python3以后元组里不加逗号替换也没有问题,python2是一定要加的。

      添加产品与修改产品接口

     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, "提交失败")
    32 
    33 
    34 @put('/api/product/<id:int>/')
    35 def callback(id):
    36     """
    37     修改记录
    38     """
    39 
    40     name = web_helper.get_form('name', '产品名称')
    41     code = web_helper.get_form('code', '产品编码')
    42     product_class_id = convert_helper.to_int0(web_helper.get_form('product_class_id', '产品分类'))
    43     standard = web_helper.get_form('standard', '产品规格')
    44     quality_guarantee_period = web_helper.get_form('quality_guarantee_period', '保质期')
    45     place_of_origin = web_helper.get_form('place_of_origin', '产地')
    46     front_cover_img = web_helper.get_form('front_cover_img', '封面图片')
    47     content = web_helper.get_form('content', '产品描述', is_check_special_char=False)
    48     # 防sql注入攻击处理
    49     content = string_helper.filter_str(content, "'")
    50     # 防xss攻击处理
    51     content = string_helper.clear_xss(content)
    52     is_enable = convert_helper.to_int0(web_helper.get_form('is_enable', '是否启用'))
    53 
    54     # 编辑记录
    55     sql = """
    56           update product
    57             set name=%s, code=%s, product_class_id=%s, standard=%s, quality_guarantee_period=%s,
    58                 place_of_origin=%s, front_cover_img=%s, content=%s, is_enable=%s
    59           where id=%s returning id"""
    60     vars = (name, code, product_class_id, standard, quality_guarantee_period, place_of_origin, front_cover_img, content,
    61             is_enable, id)
    62     # 写入数据库
    63     result = db_helper.write(sql, vars)
    64     # 判断是否提交成功
    65     if result and result[0].get('id'):
    66         return web_helper.return_msg(0, '成功')
    67     else:
    68         return web_helper.return_msg(-1, "提交失败")
    View Code

      使用非get方式提交时,即使用post、put、delete等方式提交参数时,需要使用web_helper.get_form()函数来接收,这一点大家要注意,不然就会获取不到客户端提交的参数值

        # 添加记录(使用returning这个函数能返回指定的字段值,这里要求返回新添加记录的自增id值)
        sql = """insert into product (name, code, product_class_id, standard, quality_guarantee_period,
                    place_of_origin, front_cover_img, content, is_enable)
                  values (%s, %s, %s, %s, %s, %s, %s, %s, %s) returning id"""
        vars = (name, code, product_class_id, standard, quality_guarantee_period, place_of_origin, front_cover_img, content, is_enable)
        # 写入数据库
        result = db_helper.write(sql, vars)

      新增记录时,容易出错的地方是参数中的%s与字段数量不匹配,这里大家要注意一下。另外,在insert语句的后尾最好加上returning id或returning *  返回新增记录值或整个记录实体,方便用来判断是否插入成功,如果返回这些内容的话,比较难判断数据库记录是否添加成功了

        # 编辑记录
        sql = """
              update product
                set name=%s, code=%s, product_class_id=%s, standard=%s, quality_guarantee_period=%s,
                    place_of_origin=%s, front_cover_img=%s, content=%s, is_enable=%s
              where id=%s returning id"""
        vars = (name, code, product_class_id, standard, quality_guarantee_period, place_of_origin, front_cover_img, content,
                is_enable, id)
        # 写入数据库
        result = db_helper.write(sql, vars)

      更新记录时,参数元组中记录要将记录的id值放进来,不然也会出现sql执行异常的问题,这个也是容易出错的地方。

      删除记录接口

     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, "删除失败")

      

      前端代码大家自己可以比较一下上一章,看看有什么不同

      非常感谢Sunshine-X 的提醒,在产品编辑页面的js中,添加了保存成功后jqgrid表格刷新代码(本人前端比较菜)

      后面附上完整的项目代码

      本文对应的源码下载

     

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

    python开发QQ群:669058475(本群已满)、733466321(可以加2群)    作者博客:http://www.cnblogs.com/EmptyFS/

     

  • 相关阅读:
    python 输出所有列表元素的乘积
    shell 变量赋值运算
    shell 判断变量是否为空
    js 获取地址栏域名以及URL
    python 获取列表大于指定长度的元素
    python 判断列表字符串元素首尾字符是否相同
    python 通过列表元素值截取列表并获取长度
    python 判断两个列表是否有公共元素
    python 获取列表的键值对
    python 判断列表的包含关系
  • 原文地址:https://www.cnblogs.com/EmptyFS/p/7931461.html
Copyright © 2011-2022 走看看