【亚洲必赢手机入口】自小编的首先个python,产品管理

  对于后台管理种类来说,要抓牢权限管理离不开菜单项和页面按钮控件功效的田间管理。由于程序没办法智能的精晓有怎么着菜单和控件,哪些人具有如何操作权限,所以率先要做的是菜单管理功能,将急需管理的菜单项和各类职能项添加(注册)到菜单管理表中,方便后续权限决定管理。

  接下去要做的是权力系统的数据库结构设计,在上一章我们询问了权力系统是通过怎么着来治本好权力的,大家选择其中比较常用的权力系统来促成当前项目管理需要。

  那是后台管理系列最后1个效应,产品管理,它的接口与页面效果与上一章大概。

  那是后台管理连串末段贰个功效,产品管理,它的接口与页面效果与上一章几乎。

  要支付一个菜单管理功效,离不开这几个意义:菜单列表浮现(需要菜单列表获取接口)、新增菜单(新增接口)、编辑菜单(获取菜单记录以及交付修改接口)、删除菜单(删除接口),由于菜单是多层级的涉嫌,所以还要求增添菜单树列表获取接口来绑定菜单层级,在主页面还亟需追加菜单列表项输出接口,用来展现菜单项。

  上边是大家挑选的权位系统关系模型:

亚洲必赢手机入口 1

亚洲必赢手机入口 2

  在业内编制菜单管理效果从前,大家须求先在逻辑层(logic文件夹)中添加菜单逻辑类:menu_info_logic.py,继承后边大家开发的ORubiconM基类,让目前的菜谱管理逻辑类拥有OCR-VM的具备办法。

 亚洲必赢手机入口 3

 

 

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

from logic import _logic_base
from config import db_config


class MenuInfoLogic(_logic_base.LogicBase):
    """菜单管理表逻辑类"""

    def __init__(self):
        # 表名称
        __table_name = 'menu_info'
        # 初始化
        _logic_base.LogicBase.__init__(self, db_config.DB, db_config.IS_OUTPUT_SQL, __table_name)

  从上述提到可以看来,用户登录成功之后,通过读取管理员账号新闻得到当前管理员所在单位与任务,读取职位中的权限音讯。进入系统以往,通过岗位权限音讯筛选出展现的菜单项;访问各职能页面并开展增删改查操作时,通过权限新闻判断当前管理员是否有操作权限,从而完结对系统管理员操作权限的控制。上面分别演讲一下各数据表的用处。

亚洲必赢手机入口 4

亚洲必赢手机入口 5

  为了方便管理,大家在api文件中成立system文件夹,用来存放在全体后台权限管理功用的代码,并创办menu_info.py文件,来存放在菜单管理接口

 

 

 

  亚洲必赢手机入口 6

  菜单表是用来注册(绑定)菜单、管理页面和接口用的,没有将接口和菜单项添加到菜单表的话,程序是不理解有那多少个菜单项和接口的,菜单项与接口之间存在怎么样相的涉及。

  获取产品列表接口

  获取产品列表接口

  

  所以需求在付出时,手动将它们增进到菜单表中,才能对各职能进行相应的管理。

亚洲必赢手机入口 7亚洲必赢手机入口 8

亚洲必赢手机入口 9亚洲必赢手机入口 10

  接下去我们先完毕菜单列表获取接口,由第3部分的后端管理效用可以知道,大家前端采取的是jqGrid插件,这一块我们在前方早已落到实处过了,而OLX570M中也封装好对应的形式,所以一贯调用就足以了。(这几个接口在落成时,大家要通晓驾驭的是,前端插件jqGrid它会传送什么参数和急需重返什么格式的数目回去)

  在开头设计菜单表以前,大家要寻思的是,大家须求仓储什么信息,它们之间有何样关系,每种字段有怎么着用场,为何要扩大这一个字段或调减那么些字段?

 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, "查询失败")
 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, "查询失败")

  jqGrid会通过接口,将眼下页面索引值page、页面突显记录行数rows、排序字段sidx和排序方式sord(顺序或倒序)提交到服务器端接口,尽管大家利用树列表,它还会交到当前节点id参数nodeid

  对于菜单表字段,多数字段大家都很不难定下来,比如说菜单名称、菜单url(绑定的html页面名称或路径)、菜单小图标(增添菜单的雅观度)、上一菜单id(用于建立树级菜单目录)、排序、是不是出示(对于有个别页面或按键功效,不在菜单列表中显示)、是或不是禁用(有个别功力权且不行使时,可以将它禁用掉)。除了之些之外,我们还亟需追加菜单路由地点字段,用于存储当前食谱所绑定页面所须求利用到的路由地址项,比如说编辑菜单页面,大家在开发时必要先读取那条记下出来,然后再拓展编制,最终再付诸,那里就会涉及到八个路由,三个是菜单记录读取的的路由,和菜单记录修改的路由,在做权限判断时,就可以权限当前操作页面与绑定的路由地址,跟权限新闻举办比较,判断是或不是有操作权限,具体会在末端对应章节详细表明。由于我们前端选取的是jqGrid组件的树列表效率,组件要求服务器端在回到列表时,还亟需再次回到树列表深度、当前节点是不是是最后节点、当前节点是或不是开展多个字段,所以必要将它们进入菜单表中。

View Code

View Code

  所以我们在劳动器端接口要求做好那多少个参数的吸纳与利用操作,然后大家透过调用前面完毕的OPAJEROM的get_list方法,就可以收获相应的数码再次回到给客户端了,具休代码如下:

  依据这么些须求,大家的菜单表的数据结构如下

  这几个接口多了按产品分类id查询的原则,若是少了那么些的话,间接将成品分类字段替换为产品字段变量就足以了。

  那么些接口多了按产品分类id查询的尺度,假诺少了那几个的话,直接将产品分类字段替换为产品字段变量就足以了。

 1 @get('/system/menu_info/')
 2 def callback():
 3     """
 4     获取列表数据
 5     """
 6     # 菜单列表中,当前节点id,即父节点id
 7     parent_id = convert_helper.to_int0(web_helper.get_query('nodeid', '', is_check_null=False))
 8     # 页面索引
 9     page_number = convert_helper.to_int1(web_helper.get_query('page', '', is_check_null=False))
10     # 页面页码与显示记录数量
11     page_size = convert_helper.to_int0(web_helper.get_query('rows', '', is_check_null=False))
12     # 接收排序参数
13     sidx = web_helper.get_query('sidx', '', is_check_null=False)
14     sord = web_helper.get_query('sord', '', is_check_null=False)
15     # 初始化排序字段
16     order_by = 'sort asc'
17     if sidx:
18         order_by = sidx + ' ' + sord
19 
20     _menu_info_logic = menu_info_logic.MenuInfoLogic()
21     # 读取记录
22     wheres = 'parent_id=' + str(parent_id)
23     result = _menu_info_logic.get_list('*', wheres, page_number, page_size, order_by)
24     if result:
25         return json.dumps(result)
26     else:
27         return web_helper.return_msg(-1, "查询失败")

  亚洲必赢手机入口 11

  大家可以看出此间的代码好像有点复杂。是的,那里要进行分页查询进行了分页处理,所以代码有点多,可是写了很详细的注明,只要您对python的宗旨语法、字典的处理了解,然后对以前工具函数那里按必要重写过测试用例,那么对读书那段代码是不曾怎么大题材的。

  大家可以看出此间的代码好像有个别复杂。是的,那里要拓展分页查询进行了分页处理,所以代码有点多,可是写了很详细的注释,只要你对python的中坚语法、字典的处理精通,然后对前面工具函数这里按需要重写过测试用例,那么对读书那段代码是绝非什么大难点的。

  7到18行,是收到参数。

  最后马到成功的菜谱管理页面效果如下:

  下边再重复帮大家耳熟能详一上边前讲述过的工具函数

  上面再另行帮大家熟习一上边前讲述过的工具函数

  20行起先化菜单逻辑类

  亚洲必赢手机入口 12

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

  22行是设置查询条件,默许菜单列表大家只突显第叁流菜单,约等于父id为0的菜谱。在列表第二回加载时,列表提交上去的nodeid为空(即父节点为默许为0),所以设置查询条件时父节点会赋值为parent_id=0。当大家点击树菜单进行时,才加载下一流菜单出来,那时jqGrid控件会再一次访问接口,提交当前要展开发节点id给接口,接口接收到参数今后回到对应的子节点列表给客户端。

 

  那是赢得客户端(HTML)用AJAX提交上去的出品分类id接收处理,假使你认真看过前边工具函数内容的话,看到web_helper.get_query()这几个函数应该会很纯熟,它就是得到GET形式提交值的收取函数,第叁,个参数是要收取的变量名称,第三个参数是这些变量的华语表达,第一个是在收受参数时,是还是不是做非空判断,当前设置为那不是必填项。默许它为True,当为True时,即便客户端从未提交那一个参数值,则系统活动会回来“xxx
不一致意为空”,那个xxx就是第一个参数,约等于目前变量的汉语表明,还有其余参数大家可以打看web_helper.py查看。

  那是赢得客户端(HTML)用AJAX提交上去的成品分类id接收处理,若是您认真看过前边工具函数内容的话,看到web_helper.get_query()这么些函数应该会很熟识,它就是得到GET格局提交值的收到函数,第2、个参数是要收取的变量名称,第三,个参数是其一变量的国语表达,第二个是在接受参数时,是不是做非空判断,当前设置为那不是必填项。暗中认同它为True,当为True时,假使客户端从未交给那一个参数值,则系统自动会回去“xxx
差异意为空”,这一个xxx就是第三个参数,约等于时下变量的中文表达,还有其他参数大家可以打看web_helper.py查看。

  get_list是前端O奇骏M中封装好的参数,它会回去jqGrid所急需的多寡格式,所以第15行间接将符合jqGrid须求的数据重临给列表体现出来。

  部门表它一定于权力分组,可以按照商行的单位协会,创设对应的布局记录,那样也惠及集团对系统权限关系尤其简单驾驭。当然也可以依据需求设置虚拟部门出来管理。

  convert_helper.to_int0()那么些函数,在面前工具函数第一,篇中讲到的函数,它会将收到到的参数字符串转为int类型值,假设这几个参数小于0时,会活动使用暗中同意值0代替。

  convert_helper.to_int0()这几个函数,在面前工具函数第2、篇中讲到的函数,它会将吸收到的参数字符串转为int类型值,假设这么些参数小于0时,会自行使用默认值0代替。

 

  对于部门表,首先它也是树状关系,所以它跟菜单表结构基本相仿。

 

 

  大家在后台main.html中添加菜单,方便登录后台查看效果

【亚洲必赢手机入口】自小编的首先个python,产品管理。  为了以往增加须求,要求添加单位编码字段,编码从01开头一向增进到99,当然借使单位当先九十几个的话,要么扩张到五人数,要么当前框架已不可能支撑工作的上扬需求思考新的架构了。

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

亚洲必赢手机入口 13

  编码每扩张超级,在01末尾自动扩张”0x“,编码的长短跟单位分别深度相关。

  使用习惯OPAJEROM的爱人或许会不太习惯直接写sql语句,本体系第3有的主要面向没有何基础的恋人,所以尽量不封装各系列和函数,这样大家一向看到内容会更易于精通。第壹部分会教大家本人大约包装贰个OTucsonM,到时重构后重新代码就会减小大部分。

  使用习惯O途锐M的恋人恐怕会不太习惯一贯写sql语句,本连串第贰,部分主要面向没有啥基础的情侣,所以尽大概不封装各种别和函数,那样大家一向看到内容会更易于明白。第三部分会教大家本人大致包装三个OPAJEROM,到时重构后再也代码就会优惠扣大多数。

  前端菜单管理的hmtl页面大家自行下载源码包查看,下边是做到后出示效果

  上面是机构表结构,看起来好像是在菜单表的基础上删除了成百上千字段得来的同等。

  下边那行是收获当前询问有稍许条记下的sql语句,熟稔python字符串替换的情侣应该会很纯熟,它会将字符串%前面的字典内容替代字符串中对应的键值,若是wheres值为空时,则替换空值,即将%(wheres)s那一个键值替换掉。

  上面那行是拿到当前查询有微微条记下的sql语句,精通python字符串替换的情人应该会很熟稔,它会将字符串%后面的字典内容替代字符串中对应的键值,假设wheres值为空时,则替换空值,即将%(wheres)s那个键值替换掉。

亚洲必赢手机入口 14

  亚洲必赢手机入口 15

  python的字符串替换有三种方式,而那边运用字典形式来替换会让代码可读性更高,而且字典中逐条值的职分不需求按一定方式摆放,不便于失误。

  python的字符串替换有各种方法,而那边运用字典情势来替换会让代码可读性更高,而且字典中各样值的任务不必要按一定格局摆放,不不难失误。

  由于当下还从未多少,所以目前列表是空的,上边大家成立添加和改动功能

 

 

 

 

 

  获取指定id的笔录实体

  获取指定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, "查询失败")
 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, "查询失败")

亚洲必赢手机入口 16

  所以职位表要求仓储与单位表的关系项:部门表id、部门编码、和部门名称(间接存储这一个冗余字段,是为在要求体现职位所属单位时,不必要从机构表中涉嫌查询,因为机关名称大概设置后就不会再拓展更改了)

  那段代码比较简单,第六行使用的就是%s替换字符串方式,前面的元组(id,) 
好像python3事后元组里不加逗号替换也从未难题,python2是肯定要加的。

  那段代码比较简单,第陆行使用的就是%s替换字符串方式,前边的元组(id,) 
好像python3后头元组里不加逗号替换也远非难点,python2是自然要加的。

  大家需求吸收页面提交上去的那个参数,然后向数据库中添加一条记下

  别的,它还亟需具有职位名称、菜单权限多个字段

 

 

  上级菜单选项,那里大家点击采用时,要求出示菜单树列表,让大家选拔当前新增菜单项所属菜单层级,方便菜单层级的管制,尽管为甲级菜单,则不须求开展精选

  亚洲必赢手机入口 17

  添加产品与修改产品接口

  添加产品与修改产品接口

  为了让后台菜单赏心悦目一些,我们能够追加菜单小图标,H-ui框架中,提供了字体图标,这里的查阅扩充链接到官网中,可以直接询问字体图标编码复制过来使用

  页面效果图:

亚洲必赢手机入口 18亚洲必赢手机入口 19

亚洲必赢手机入口 20亚洲必赢手机入口 21

  排序可以输入任意的数字,通过从
小到明清序排列菜单项,为了便于排序项可以活动累加,代码中得以拿走当前菜谱层级最大值加1的点子来展开赋值

  亚洲必赢手机入口 22

 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, "提交失败")
 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, "提交失败")
 1 @post('/api/system/menu_info/')
 2 def callback():
 3     """
 4     新增记录
 5     """
 6     name = web_helper.get_form('name', '菜单名称')
 7     icon = web_helper.get_form('icon', '菜单小图标', True, 10, False, is_check_special_char=False)
 8     icon = icon.replace('\'', '').replace('|', '').replace('%', '')
 9     page_url = web_helper.get_form('page_url', '页面URL', is_check_null=False)
10     interface_url = web_helper.get_form('interface_url', '接口url', is_check_null=False, is_check_special_char=False)
11     # 替换编码
12     interface_url = interface_url.replace('@', '').replace('\'', '').replace('|', '').replace('%', '')
13     parent_id = convert_helper.to_int0(web_helper.get_form('parent_id', '父id', is_check_null=False))
14     sort = convert_helper.to_int0(web_helper.get_form('sort', '排序', is_check_null=False))
15     is_leaf = web_helper.get_form('is_leaf', '是否最终节点', is_check_null=False)
16     is_show = web_helper.get_form('is_show', '是否显示', is_check_null=False)
17     is_enabled = web_helper.get_form('is_enabled', '是否启用', is_check_null=False)
18 
19     _menu_info_logic = menu_info_logic.MenuInfoLogic()
20     # 计算深度级别,即当前菜单在哪一级
21     if parent_id == 0:
22         level = 0
23     else:
24         level = _menu_info_logic.get_value_for_cache(parent_id, 'level') + 1
25     # 如果没有设置排序,则自动获取当前级别最大的序号加1
26     if sort == 0:
27         sort = _menu_info_logic.get_max('parent_id', 'parent_id=' + str(parent_id)) + 1
28 
29     # 组合更新字段
30     fields = {
31         'name': string(name),
32         'icon': string(icon),
33         'page_url': string(page_url),
34         'interface_url': string(interface_url),
35         'parent_id': parent_id,
36         'sort': sort,
37         'level': level,
38         'is_leaf': is_leaf,
39         'is_show': is_show,
40         'is_enabled': is_enabled,
41     }
42     # 新增记录
43     result = _menu_info_logic.add_model(fields)
44     if result:
45         return web_helper.return_msg(0, '提交成功')
46     else:
47         return web_helper.return_msg(-1, "提交失败")

  亚洲必赢手机入口 23

View Code

View Code

  前端菜单新增页面(menu_info_edit.html)大家下载源码包查看

 

  使用非get格局交给时,即接纳post、put、delete等方法提交参数时,须要选用web_helper.get_form()函数来接过,这点大家要注意,不然就会赢得不到客户端提交的参数值

  使用非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)
    # 添加记录(使用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)

  新增菜单页面树列表大家应用的是zTree插件,它须要大家输出指定的数量格式才能平常呈现,所以调用接口再次来到:id、parent_id、name、open那些字段,在菜单项中,大家有是不是最后节点的字段,所以查询条件中大家指定询问出具有非最终节点的项就可以了

  而大班账号管理,紧要管理的是后台管理员登录账号与密码,管理员的主干音讯,还有操作权限。

  新增记录时,简单失误的地点是参数中的%s与字段数量不包容,那里我们要小心一下。别的,在insert语句的后尾最好拉长returning
id或returning * 
重回新增记录值或任何记录实体,方便用来判定是不是插入成功,假若回去那个内容的话,比较难判断数据库记录是不是丰硕成功了

  新增记录时,不难出错的地点是参数中的%s与字段数量不般配,那里大家要注意一下。别的,在insert语句的后尾最好增进returning
id或returning * 
重返新增记录值或任何记录实体,方便用来判断是或不是插入成功,要是回到那一个情节的话,相比较难断定数据库记录是不是丰裕成功了

 1 @get('/api/system/menu_info/tree/')
 2 def callback():
 3     """
 4     获取列表数据(树列表)
 5     """
 6     _menu_info_logic = menu_info_logic.MenuInfoLogic()
 7     # 读取记录
 8     result = _menu_info_logic.get_list('id, parent_id, name, not is_leaf as open', 'is_leaf=false', orderby='sort asc')
 9     if result:
10         return web_helper.return_msg(0, "成功", {'tree_list': result.get('rows')})
11     else:
12         return web_helper.return_msg(-1, "查询失败")

  而权力的军事管制只需求绑定对应的机关与任务,在用户登录时就足以经过这么些绑定获取相应的操作权限。

    # 编辑记录
    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)
    # 编辑记录
    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)

  完结后直接填写参数就足以交给新增菜单记录了。

  一般的话,管理员账号须要记录:登陆账号、登录密码、登录密钥(若是急需经过APP端登录、要求对走访链接加密可能启用cookies验证登录的,需求这几个字段来存储用户自身相应的密钥)、最终登录时间、最后登录id、登录次数、注册时间等音信

  更新记录时,参数元组中记录要将记录的id值放进来,不然也会合世sql执行极度的题目,那么些也是不难失误的地点。

  更新记录时,参数元组中记录要将记录的id值放进来,不然也会产出sql执行万分的标题,那一个也是简单失误的地方。

  亚洲必赢手机入口 24

  而大班的主题音讯,则是依照差别商店的田间管理需要不相同而各异,有的将人事管理也丰盛到系统中,则必要记录每一个职工的具备主题新闻,当然常用的新闻有:用户汉语名称、性别、出生日期、手机号码、邮箱、备注,我们依据要求自行添加或删除。

 

 

  对于编辑接口,它基本上和新增接口代码相差不大,不相同地点有上面几点:

  而用户的权杖相关字段,紧借使绑定部门与地方,和行事状态和账号状态它些字段了。

  删除记录接口

  删除记录接口

  1.为了裁减菜单层级变更所造成的谬误,在编写记录接口大家必要遮掩对父节点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, "删除失败")
 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, "删除失败")

  2.不须要再总结当前食谱所在层级的纵深

  亚洲必赢手机入口 25

  

  

  3.将新增方法add_model()更改为edit_model()方法

  页面效果图:

  前端代码大家自身可以比较一下上一章,看看有怎样差异

亚洲必赢手机入口,  前端代码我们自个儿可以比较一下上一章,看看有如何两样

 1 @put('/api/system/menu_info/<id:int>/')
 2 def callback(id):
 3     """
 4     修改记录
 5     """
 6     name = web_helper.get_form('name', '菜单名称')
 7     icon = web_helper.get_form('icon', '菜单小图标', True, 10, False, is_check_special_char=False)
 8     icon = icon.replace('\'', '').replace('|', '').replace('%', '')
 9     page_url = web_helper.get_form('page_url', '页面URL', is_check_null=False)
10     interface_url = web_helper.get_form('interface_url', '接口url', is_check_null=False, is_check_special_char=False)
11     # 替换编码
12     interface_url = interface_url.replace('\'', '').replace('|', '').replace('%', '')
13     parent_id = convert_helper.to_int0(web_helper.get_form('parent_id', '父id', is_check_null=False))
14     sort = convert_helper.to_int0(web_helper.get_form('sort', '排序', is_check_null=False))
15     is_leaf = web_helper.get_form('is_leaf', '是否最终节点', is_check_null=False)
16     is_show = web_helper.get_form('is_show', '是否显示', is_check_null=False)
17     is_enabled = web_helper.get_form('is_enabled', '是否启用', is_check_null=False)
18 
19     _menu_info_logic = menu_info_logic.MenuInfoLogic()
20     # 如果没有设置排序,则自动获取当前级别最大的序号加1
21     if sort == 0:
22         sort = _menu_info_logic.get_max('parent_id', 'parent_id=' + str(parent_id)) + 1
23 
24     # 组合更新字段
25     fields = {
26         'name': string(name),
27         'icon': string(icon),
28         'page_url': string(page_url),
29         'interface_url': string(interface_url),
30         'sort': sort,
31         'is_leaf': is_leaf,
32         'is_show': is_show,
33         'is_enabled': is_enabled,
34     }
35     # 修改记录
36     result = _menu_info_logic.edit_model(id, fields)
37     if result:
38         return web_helper.return_msg(0, '提交成功')
39     else:
40         return web_helper.return_msg(-1, "提交失败")

  亚洲必赢手机入口 26

  相当谢谢Sunshine-X
的升迁,在成品编辑页面的js中,添加了保留成功后jqgrid表格刷新代码(本人前端比较菜)

  格外谢谢Sunshine-X
的指示,在产品编辑页面的js中,添加了保留成功后jqgrid表格刷新代码(本人前端比较菜)

  大家可以相比一下猛增与编制接口代码,可以发现代码大致都以一模一样的。

  亚洲必赢手机入口 27

  前边附上完整的品类代码

  前边附上完整的门类代码

  亚洲必赢手机入口 28

 

 

 

 

  做来管理连串,当然还索要记录管理员的富有操作记录,比如登录、退出、浏览了什么页面,操作过如何,所以还要加进三个大班操作日志表,方便查看分析难点,分清权利

 

 

  最终增加删除接口

  亚洲必赢手机入口 29

  本文对应的源码下载

  正文对应的源码下载

 1 @delete('/api/system/menu_info/<id:int>/')
 2 def callback(id):
 3     """
 4     删除指定记录
 5     """
 6     _menu_info_logic = menu_info_logic.MenuInfoLogic()
 7     # 判断要删除的节点是否有子节点,是的话不能删除
 8     if _menu_info_logic.exists('parent_id=' + str(id)):
 9         return web_helper.return_msg(-1, "当前菜单存在子菜单,不能直接删除")
10 
11     # 删除记录
12     result = _menu_info_logic.delete_model(id)
13     if result:
14         return web_helper.return_msg(0, '删除成功')
15     else:
16         return web_helper.return_msg(-1, "删除失败")

 

 

 

  删除接口跟前端产品分类删除接口一样,在剔除前须要看清当前食谱是还是不是已被引用(即日前菜谱下是还是不是留存子菜单)

  权限管理数据表成立sql下载
(PS:为了便利操作,sql会将事先创立的manager表删除,然后再度添加admin管理员账号进入)

版权注解:本文原创发表于 博客园,作者为 AllEmpty 本文欢迎转发,但未经作者同意必须保留此段评释,且在作品页面分明地方给出原文连接,否则视为侵权。

版权注解:本文原创公布于 博客园,作者为 AllEmpty 本文欢迎转载,但未经我同意必须保留此段声明,且在篇章页面显著地点给出原文连接,否则就是侵权。

 

 

python开发QQ群:669058475   
我博客:

python开发QQ群:669058475   
我博客:

  菜单管理项添加已毕后,列表效果图

 

 

 

亚洲必赢手机入口 30

版权表明:本文原创公布于 博客园,作者为 AllEmpty 正文欢迎转发,但未经小编同意必须保留此段注脚,且在作品页面显然地方给出原文连接,否则就是侵权。

 

python开发QQ群:669058475   
小编博客:

  完结那些之后,我们还亟需改造一下管理主界面左栏的菜种类表,改为从菜系管理数据表中读取方式

  为了有利于后续权限的管理改造,我们在接口中组成菜单代码来贯彻菜单的显得效果。

  首先大家由此翻看左栏菜单列表的html代码,提取出菜单html展现代码

  然后在接口中,获取设置为体现并启用情形的食谱列表

  通过轮回判断,拼接一流菜单和二级菜单项的html输出代码

  最终将结果输出到前端显示出来

 1 @get('/api/main/menu_info/')
 2 def callback():
 3     """
 4     主页面获取菜单列表数据
 5     """
 6     _menu_info_logic = menu_info_logic.MenuInfoLogic()
 7     # 读取记录
 8     result = _menu_info_logic.get_list('*', 'is_show and is_enabled', orderby='sort')
 9     if result:
10         # 定义最终输出的html存储变量
11         html = ''
12         for model in result.get('rows'):
13             # 提取出第一级菜单
14             if model.get('parent_id') == 0:
15                 # 添加一级菜单
16                 temp = """
17                 <dl id="menu-%(id)s">
18                     <dt><i class="Hui-iconfont">%(icon)s</i> %(name)s<i class="Hui-iconfont menu_dropdown-arrow">&#xe6d5;</i></dt>
19                     <dd>
20                         <ul>
21                 """ % {'id': model.get('id'), 'icon': model.get('icon'), 'name': model.get('name')}
22                 html = html + temp
23 
24                 # 从所有菜单记录中提取当前一级菜单下的子菜单
25                 for sub_model in result.get('rows'):
26                     # 如果父id等于当前一级菜单id,则为当前菜单的子菜单
27                     if sub_model.get('parent_id') == model.get('id'):
28                         temp = """
29                         <li><a data-href="%(page_url)s" data-title="%(name)s" href="javascript:void(0)">%(name)s</a></li>
30                     """ % {'page_url': sub_model.get('page_url'), 'name': sub_model.get('name')}
31                         html = html + temp
32 
33                 # 闭合菜单html
34                 temp = """
35                         </ul>
36                     </dd>
37                 </dl>
38                     """
39                 html = html + temp
40 
41         return web_helper.return_msg(0, '成功', {'menu_html': html})
42     else:
43         return web_helper.return_msg(-1, "查询失败")

  执行后会输出上面结果:

{
    "data": {
        "menu_html": "\n                <dl id=\"menu-1\">\n                    <dt><i class=\"Hui-iconfont\">&#xe62e;</i> 系统管理<i class=\"Hui-iconfont menu_dropdown-arrow\">&#xe6d5;</i></dt>\n                    <dd>\n                        <ul>\n                \n                        <li><a data-href=\"menu_info.html\" data-title=\"菜单管理\" href=\"javascript:void(0)\">菜单管理</a></li>\n                    \n                        </ul>\n                    </dd>\n                </dl>\n                    "
    },
    "msg": "成功",
    "state": 0
}

  前端通过AJAX获取菜单列表hmtl代码,然后添加到后台左栏菜单列表中就达成大家想要的效益了

<aside class="Hui-aside">
    <div class="menu_dropdown bk_2" id="menu">

    </div>
</aside>


<script type="text/javascript">
    $(function () {
        $.ajax({
            url: "/api/main/menu_info/?" + 100 * Math.random(),
            type: "GET",
            dataType:'json',
            success: function (data) {
                if (checkLogin(data, true))
                {
                    $("#menu").html(data.data.menu_html);
                    $.Huifold(".menu_dropdown dl dt",".menu_dropdown dl dd","fast",1,"click");
                }
            }
        });
    });
</script>

  页面突显效果

亚洲必赢手机入口 31

  对于菜单管理的改建,完结地点那么些项尽管完厉了。对于菜单权限的操纵,后续完毕全套改造后会专门讲解。

 

  权限系统中的部门管理(角色权限组管理),它的基本效用和菜单功用相似,所以就不开新章节进行讲解,大家可以根据数据结构尝试编写,也足以参考本节提供的源码进行研商。

  PS:部门管理中,部门编码生成是二个相比较特别的法门,须求多debug掌握。

 

 

  本文对应的源码下载 (内附本章源码对应数据库表单和笔录创设sql代码,上传的图形假诺展现不断,可以nginx.conf配置的location项中添加upload,第二有的章节的nginx那里忘记添加了)

 

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

python开发QQ群:669058475   
小编博客:

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图