django 09
上节我们在中间部分显示出了produce信息,现在我们将这些信息进行分页。
首先在manager页面中js的$('#dg')中添加:
$('#dg').datagrid({
url:'ProduceList',
pagination:true,
pageList:[5,10,15],
columns:[[
{field:'id',title:'编号',width:100},
{field:'name',title:'名字',width:100},
{field:'price',title:'价格',width:100,align:'right'},
{field:'create_date',title:'发布时间',width:100,align:'right'}
]],
});
pagination:true, 为开启分页 pageList:[5,10,15] 为分页模式可以为5、10或者15页。
然后我们在views中的ProduceList添加分页器:
@csrf_exempt
def ProduceList(request):
page = request.POST.get('page',1)#默认第一页
rows = request.POST.get('rows',10)#默认每页10条
proSet = Produce.objects.all().order_by('id')
#创建分页器
paginator = Paginator(proSet,rows)
#获取第几页的数据
pages = paginator.get_page(page)
#返回值中必须有 总页数total和 当前页rows
tree = []
for pro in pages:
p={}
p['id'] = pro.id
p['name'] = pro.name
p['price'] = pro.price
p['create_date'] = pro.create_date.strftime('%Y-%m-%d')
p['category'] = pro.category.name
tree.append(p)
grid = {'total': paginator.count,
'rows':tree,
}
return HttpResponse(json.dumps(grid))
首先需要注意倒包和装饰器的添加。设置两个值,分别为page(获取当前page,如果没有则默认第一页)和rows(如不设置,默认按10条/页 分页),然后创建分页器paginator并获取当前第几页页的数据,接着将for循环中遍历的proSet改为pages,遍历当前页,最后创建一个grid字典形式的参数,里面储存了total和rows,分别为页的总数及tree。现在打开页面即为:
但是现在还有许多问题,比如我们应该点击左侧树状栏,点击那个类,中间就显示哪个类的产品;又或者我们点击名字或者价格,可以是列表按顺序排序。下面我们就解决这两个问题。
1).第一个问题的解决。首先我们js中的$('#tt') 中添加一个onclick 事件,使得点击时会重新获取node.id 并将这个id传回到$('#dg')中,并查询这个id的从而使列表发生变化:
$('#tt').tree({
url:'catetree',
onClick:function (node) {
$('#dg').datagrid({
queryParams:{
'category_id':node.id
}
})
}
});
queryParams 为datagrid的参数,为当请求远程数据时,发送的额外参数。 这里将点击获取的id以category_id传回到后台views中。
下面是views中的处理:
@csrf_exempt
def ProduceList(request):
#获取某个类别下的产品
cate_id = request.POST.get('category_id', None)
page = request.POST.get('page',1)#默认第一页
rows = request.POST.get('rows',10)#默认每页10条
proSet = Produce.objects.all()
if cate_id is not None:
proSet=proSet.filter(category_id=cate_id)
#创建分页器
paginator = Paginator(proSet,rows)
#获取第几页的数据
pages = paginator.get_page(page)
#返回值中必须有 总页数total和 当前页rows
tree = []
for pro in pages:
p={}
p['id'] = pro.id
p['name'] = pro.name
p['price'] = pro.price
p['create_date'] = pro.create_date.strftime('%Y-%m-%d')
p['category'] = pro.category.name
tree.append(p)
grid = {'total': paginator.count,
'rows':tree,
}
return HttpResponse(json.dumps(grid))
还是上面的方法,只是添加了 获取上述传入的category_id并复制给cate_id,添加了一个判断,当cate_id不为空时,proSet为筛选出category_id=cate_id的集。
2)第二个问题的解决。在js中添加:
$('#dg').datagrid({
url:'ProduceList',
pagination:true,
pageList:[5,10,15],
columns:[[
{field:'id',title:'编号',width:100},
{field:'name',title:'名字',width:100,sortable:true},
{field:'price',title:'价格',width:100,sortable:true,align:'right'},
{field:'create_date',title:'发布时间',width:100,align:'right'}
]],
});
添加了sortable,并设置为true,意为可以排序。这时打开浏览器localhost:8000,查看network的ProduceList表中的Form Data可以发现新增了两个参数:sort和order 现在我们将这两个参数加入到后台中:
@csrf_exempt
def ProduceList(request):
#获取某个类别下的产品
cate_id = request.POST.get('category_id', None)
#获取排序的列和排序方式
sort = request.POST.get('sort', 'id')#排序的列,默认id
order = request.POST.get('order', 'asc')#排序的列,默认asc
page = request.POST.get('page',1)#默认第一页
rows = request.POST.get('rows',10)#默认每页10条
proSet = Produce.objects.all()
if cate_id is not None:
proSet=proSet.filter(category_id=cate_id)
if order != 'asc':
sort='-'+sort
proSet = proSet.order_by(sort)
#创建分页器
paginator = Paginator(proSet,rows)
#获取第几页的数据
pages = paginator.get_page(page)
#返回值中必须有 总页数total和 当前页rows
tree = []
for pro in pages:
p={}
p['id'] = pro.id
p['name'] = pro.name
p['price'] = pro.price
p['create_date'] = pro.create_date.strftime('%Y-%m-%d')
p['category'] = pro.category.name
tree.append(p)
grid = {'total': paginator.count,
'rows':tree,
}
return HttpResponse(json.dumps(grid))
获取了sort和order,默认为id/asc,因为排序在程序中为+- 正负,所以我们判断一下当前的order是否不等于asc,如果不等于,赋予负值,然后将proSet以sort排序。 现在我们打开页面即可实现上述两个事件。
现在我们使用toolbar 在我们的表格上添加几个按钮。
toolbar: 顶部工具栏的DataGrid面板。可能的值有
1) 一个数组,每个工具属性都和linkbutton一样。
2) 选择器指定的工具栏。
在$('#dg')中添加:
$('#dg').datagrid({
url:'ProduceList',
pagination:true,
pageList:[5,10,15],
columns:[[
{field:'id',title:'编号',width:100},
{field:'name',title:'名字',width:100,sortable:true},
{field:'price',title:'价格',width:100,sortable:true,align:'right'},
{field:'create_date',title:'发布时间',width:100,align:'right'}
]],
toolbar: [
{
iconCls: 'icon-add',
text:'添加',
handler: function(){}
},'-',{
iconCls: 'icon-edit',
text:'编辑',
handler: function(){}
},'-',
{
iconCls: 'icon-remove',
text:'删除',
handler: function(){}
},'-',
{
iconCls: 'icon-help',
text:'帮助',
handler: function(){}
}]
});
现在打开页面会显示:
现在我们来做第一个按钮-->添加。点击添加之后应该有一个弹窗而不是跳转页面,然后添加页面中应该有产品名字、价格、类别、创建时间。
现在我们在manager中创建一个div用来作为弹窗:
<div id="newPro">
<form id="ff" method="post" action="">
<div>
<label>产品名称:</label>
<input class="easyui-validatebox" type="text" name="name" data-options="required:true" />
</div>
<div>
<label>价格:</label>
<input name="price" type="text" class="easyui-numberbox" value="100" data-options="min:0,precision:2">
</div>
<div>
<label>品种类别:</label>
<select name="cata" id="Category" class="easyui-combotree" style="width:200px;"
data-options="required:true"></select>
</div>
<div>
<label>时间:</label>
<input class="easyui-datetimebox" name="createDate"
data-options="required:true,showSeconds:false" value="" style="width:150px">
</div>
</form>
</div>
价格中class设置为:easyui-numberbox 为只能填写数字 ,默认100
品种类别class设置为:easyui-combotree 使得select下拉列表为一个树状结构,且设置了id为Category
时间 class设置为:easyui-datetimebox 和日期输入框类似,日期时间输入框允许用户选择日期和指定的时间并按照指定的输出格式显示。相比日期输入框,它在下拉面板中添加了一个时间微调器。
下面我们添加js中的newPro,使其隐藏:
$('#newPro').dialog({
title: '添加产品',
width: 400,
height: 200,
closed: true,
cache: false,
modal: true
});
然后在toolbar中的add 中的handler中添加:
{
iconCls: 'icon-add',
text:'添加',
handler: function(){
var node = $("#tt").tree("getSelected");
$('#newPro').dialog('open');
}
}
首先在点击添加时,将newPro 打开,然后设置node为再次获取tt中的树模型。
产品类别id为Category ,最后继续在js中添加:
$('#Category').combotree({
required:true,
url:'/catetree'
});
路径为catetree方法,在打开add的时候就已经获取了tree。
现在点击添加显示:
但是现在仍不是我们想要的结果,我们应该做成当点击左侧树状结构的任意类别,再点添加时,品种类别会自动显示那个类别。
继续在add中添加:
{
iconCls: 'icon-add',
text:'添加',
handler: function(){
var node = $("#tt").tree("getSelected");
if(node){
//取消异步请求
$.ajaxSetup({
async:false
});
$('#Category').combotree('tree').tree({
onLoadSuccess:function (node,date) {
$('#Category').combotree('tree').tree('expandAll')
}
});
//开启异步请求
$.ajaxSetup({
async:true
});
//将选中的类别的id绑定到下拉列表中
$('#ff').form('load',{cata:node.id});
}
$('#newPro').dialog('open');
}
}
首先关闭ajax,产生的效果为当打开add时,下面的加载tree的代码没加载完时,添加产品的div不会显示。
onloadSuccess 为当数据载入成功时触发
expendAll 为展开树中的所有节点。
上述关闭ajax后的代码意为:返回Category 以树的结构返回,节点为当数据载入成功时,获取并展开Category树的所有节点。这段代码为同步请求。
然后开启ajax(开启异步请求),将我们选中的类别id绑定到下拉列表中。
现在打开页面可显示:
可以发现network中有很多个catetree,选定类别打开添加需要等一会,这些我们后面有机会的话试着优化。