問題背景
在筆者文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