由于之前的源码中少了产品分类的页面,所以需要将main.html、products_class.html、product_class_edit.html复制到html文件夹下面。然后进入后台的界面就变成了这个样子:

对于产品分类列表,我们将使用jqgrid前端表格框架,jqGrid 是一个用来显示网格数据的jQuery插件,通过使用jqGrid可以轻松实现前端页面与后台数据的ajax异步通信。
jqgrid与接口交互时,它会提交页面索引、页面大小、排序字段名以及顺序还是倒序排序这几个参数,而返回的结果也有格式约束。
返回格式要求:
{
'records': 0,
'total': 0,
'page': 1,
'rows': [],
}
一、产品分类列表获取接口
在api目录下在,新建一个product_class.py文件,代码如下:
#!/usr/bin/evn python
# coding=utf-8
import json
from bottle import get, put, post, delete
from common import web_helper, db_helper, convert_helper, json_helper
@get('/api/product_class/')
def callback():
"""
获取列表数据
"""
# 页面索引
page_number = convert_helper.to_int1(web_helper.get_query('page', '', False))
# 页面显示记录数量
page_size = convert_helper.to_int0(web_helper.get_query('rows', '', False))
# 排序字段
sidx = web_helper.get_query('sidx', '', False)
# 顺序还是倒序排序
sord = web_helper.get_query('sord', '', False)
# 初始化排序字段
order_by = 'sort asc'
if sidx:
order_by = sidx + ' ' + sord
#############################################################
# 初始化输出格式(前端使用jqgrid列表,需要指定输出格式)
data = {
'records': 0,
'total': 0,
'page': 1,
'rows': [],
}
#############################################################
# 执行sql,获取指定条件的记录总数量
sql = 'select count(1) as records from product_class'
result = db_helper.read(sql)
# 如果查询失败或不存在指定条件记录,则直接返回初始值
if not result or result[0]['records'] == 0:
return data
# 保存总记录数量
data['records'] = result[0].get('records', 0)
#############################################################
### 设置分页索引与页面大小 ###
# 设置分页大小
if page_size is None or page_size <= 0:
page_size = 10
# 计算总页数
if data['records'] % page_size == 0:
page_total = data['records'] // page_size
else:
page_total = data['records'] // page_size + 1
# 记录总页面数量
data['total'] = page_total
# 判断提交的页码是否超出范围
if page_number < 1 or page_number > page_total:
page_number = page_total
# 记录当前页面索引值
data['page'] = page_number
# 计算当前页面要显示的记录起始位置
record_number = (page_number - 1) * page_size
# 设置查询分页条件
paging = ' limit ' + str(page_size) + ' offset ' + str(record_number)
### 设置排序 ###
if not order_by:
order_by = 'id desc'
#############################################################
# 组合sql查询语句
sql = "select * from product_class order by %(orderby)s %(paging)s" % \
{'orderby': order_by, 'paging': paging}
# 读取记录
result = db_helper.read(sql)
if result:
# 存储记录
data['rows'] = result
if data:
# 直接输出json
return web_helper.return_raise(json.dumps(data, cls=json_helper.CJsonEncoder))
else:
return web_helper.return_msg(-1, "查询失败")
这段代码有点长,从功能上可以分为四段,第一段是接收客户端提交的参数;第二段获取当前查询条件下有多少条记录数量;第三段是处理分页,并组合查询sql语句;第四段是提交查询请求,并返回结果
get方式提交,我们使用web_helper.get_query()函数获取参数值。
二、删除接口
product_class.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, "删除失败")
在做删除前,需要判断一下这个分类是否已经被相关的产品引用绑定了,如果是的话,直接删除将会造成前端相关产品无法展示,所以需要做出提醒,让用户清除绑定后再进行删除操作。
三、新增记录接口
product_class.py添加以下代码:
@post('/api/product_class/')
def callback():
"""
新增记录
"""
name = web_helper.get_form('name', '分类名称')
is_enable = convert_helper.to_int0(web_helper.get_form('is_enable', '是否启用'))
# 添加记录(使用returning这个函数能返回指定的字段值,这里要求返回新添加记录的自增id值)
sql = """insert into product_class (name, is_enable) values (%s, %s) returning id"""
vars = (name, is_enable)
# 写入数据库
result = db_helper.write(sql, vars)
# 判断是否提交成功
if result and result[0].get('id'):
return web_helper.return_msg(0, '成功')
else:
return web_helper.return_msg(-1, "提交失败")
四、编辑记录接口
product_class.py添加代码如下。
@get('/api/product_class/<id:int>/')
def callback(id):
"""
获取指定记录
"""
sql = """select * from product_class where id = %s""" % (id,)
# 读取记录
result = db_helper.read(sql)
if result:
# 直接输出json
return web_helper.return_msg(0, '成功', result[0])
else:
return web_helper.return_msg(-1, "查询失败")
@put('/api/product_class/<id:int>/')
def callback(id):
"""
修改记录
"""
name = web_helper.get_form('name', '分类名称')
is_enable = convert_helper.to_int0(web_helper.get_form('is_enable', '是否启用'))
# 编辑记录
sql = """update product_class set name=%s, is_enable=%s where id=%s returning id"""
vars = (name, is_enable, id)
# 写入数据库
result = db_helper.write(sql, vars)
# 判断是否提交成功
if result and result[0].get('id'):
return web_helper.return_msg(0, '成功')
else:
return web_helper.return_msg(-1, "提交失败")
五、测试代码
点击“添加”按钮,输入相关内容,点击“提交”。

然后可以看到添加的内容,表示添加成功了。

然后再测试一下编辑、删除功能,如果没问题的话就OK了。
六、联系我们页面
(一)新增数据库信息
同前面的公司介绍一样,先在数据库中插入一条记录。
INSERT INTO infomation(id, title) VALUES (2, '联系我们');
(二)联系我们页面
在api文件夹下面新增一个contact_us.py文件,代码如下:
#!/usr/bin/evn python
# coding=utf-8
from bottle import get, put
from common import web_helper, string_helper, db_helper
@get('/api/contact_us/')
def callback():
"""
获取指定记录
"""
sql = """select * from infomation where id = 2"""
# 读取记录
result = db_helper.read(sql)
if result:
# 直接输出json
return web_helper.return_msg(0, '成功', result[0])
else:
return web_helper.return_msg(-1, "查询失败")
@put('/api/contact_us/')
def callback():
"""
修改记录
"""
content = web_helper.get_form('content', '内容', is_check_special_char=False)
# 防sql注入攻击处理
content = string_helper.filter_str(content, "'")
# 防xss攻击处理
content = string_helper.clear_xss(content)
# 更新记录
sql = """update infomation set content=%s where id=2 returning id"""
vars = (content,)
# 写入数据库
result = db_helper.write(sql, vars)
if result and result[0].get('id'):
return web_helper.return_msg(0, '成功')
else:
return web_helper.return_msg(-1, "提交失败")
(三)测试
在浏览器输入:http://127.0.0.1:9090/api/contact_us/,看到如下界面,里面有“ "state": 0”的信息,就表示成功了。

转码后的结果:
