问题背景
在笔者文Django - 如何实现用户进行数据查询(表格)的功能?datatable - client processing谈到在使用datatable使用client processing的时候,存在以下两个问题:
- 数据库太大的时候,比如有百万级别数据的时候, 一次性发送json数据的速度就有待考证。
- 前端一次性获得数据之后,再分页的时候,都是上次浏览的时候缓存的数据处理的,那么在用户眼前的数据可能并不是服务器中实时的数据
本文将讲述,如何通过使用datatable插件的自带能力 server processing来解决这两个问题。
HTML实现
<div class="col-md-12">
<table class="table table-striped table-bordered table-hover table-checkable order-column" id="sample_1">
<thead>
<tr>
<th>
<label class="mt-checkbox mt-checkbox-single mt-checkbox-outline">
<input type="checkbox" class="group-checkable" data-set="#sample_1 .checkboxes"/>
<span></span>
</label>
</th>
<th> 书名</th>
<th> 出版社</th>
<th> 借阅次数</th>
<th> 数量</th>
<th> 作者</th>
<th> 状态</th>
<th> ISBN</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
HTML实现和使用client processing的方式保持一致,并没有什么不同。
js 实现
$(document).ready(function() {
$("#sample_1").dataTable(
{
searching : false,
destroy : true,
"processing" : true,
"serverSide" : true,
"ajax": {
"url": "book/query/",
"type": "POST",
"data": function(d){
return $.extend( {}, d, {
"author" : document.getElementById('id_author').value,
"press" : document.getElementById('press').value,
"isbn" : document.getElementById('isbn').value,
"name" : document.getElementById('book').value,
"status" : document.getElementById('status').value
});
}
},
columns: [
{ },
{ data: 'name' },
{ data: 'press' },
{ data: 'lendCount' },
{ data: 'acount' },
{ data: 'author' },
{ data: 'status' },
{ data: 'isbn' }
],
'columnDefs': [{
'targets': 0,
'searchable': false,
'orderable': false,
'className': 'select-checkbox',
'render': function (data, type, full, meta){
return '<label class="mt-checkbox mt-checkbox-single mt-checkbox-outline"><input type="checkbox" class="checkboxes" value="1"/><span></span></label>'
}
}],
}
);
});
和clinet processing相比, 在需要使用datatable的server processing的特性的时候, 有以下注意点:
- 将 processing 和 serverSide 选项置为 true
- 说明ajax:type为 POST
- 指定处理该ajax请求的url,如本例中的"url":"book/query", 该url需要在Django后台的urls.py中注册
Django实现
def post(self, request):
if request.method == "POST":
dumpRequest(request)
objects = Book.objects.all()
recordsTotal = objects.count()
recordsFiltered = recordsTotal
start = int(request.POST['start'])
length = int(request.POST['length'])
draw = int(request.POST['draw'])
objects = objects[start:(start + length)]
dic = [obj.as_dict() for obj in objects]
resp = {
'draw': draw,
'recordsTotal': recordsTotal,
'recordsFiltered': recordsFiltered,
'data': dic,
}
return HttpResponse(json.dumps(resp), content_type="application/json")
在使用datatable的server processing的时候, 后端返回给前端的数据需要以jason格式返回, 而且返回的数据格式也有要求。 如果说返回的数据格式不匹配,datatable插件会弹框提示出错信息。
在本例子中,我们的返回信息包括以下内容
- draw 这一项将获取到的ajax json request中的数据,转成int返回
- recordsTotal 所有记录的条数
- recordsFiltered 过滤之后的记录的条数
-
data 返回的表格的内容数据
在之前ajax request中,还有一个关于data域的内容也值得一提
"data": function(d){
return $.extend( {}, d, {
"author" : document.getElementById('id_author').value,
"press" : document.getElementById('press').value,
"isbn" : document.getElementById('isbn').value,
"name" : document.getElementById('book').value,
"status" : document.getElementById('status').value
});
}
},
这段代码所起的作用是说,在ajax request的内容里面不仅仅包括datatables生成的内容, 还包含DOM里面id_author/press/isbn/book/status这5个input控件的值。这样Django后台可以根据这几个值去做数据过滤。
我们只需将form表单的submit做如下实现,即可在用户点击form表单提交按钮的时候, 进行数据查询呢
$("form").submit(function(e){
e.preventDefault();
table = $("#sample_1").DataTable();
table.ajax.reload();
});
下一篇文章,我们将来讲述在server processing的情况下,如何实现数据过滤和排序
参考
- 官方关于server processing make post request的说明https://www.datatables.net/examples/server_side/post.html