DjangoWeb使用Datatable進(jìn)行后端分頁(yè)的實(shí)現(xiàn)
使用場(chǎng)景:不使用Django的模版語(yǔ)言進(jìn)行分頁(yè)(網(wǎng)上大多數(shù)都使用該方式),使用Jquery DataTable.js 插件進(jìn)行分頁(yè)處理。
本人做的是一個(gè)表格監(jiān)控頁(yè)面,該頁(yè)面中的table內(nèi)容每5s刷新一次。
注意:這種方式非長(zhǎng)連接(websocket)模式,長(zhǎng)連接模式也有弊端,因網(wǎng)絡(luò)波動(dòng)導(dǎo)致,倘若一次連接斷開(kāi),后面將無(wú)法繼續(xù)刷新數(shù)據(jù)(不重連的話(huà)),且比較吃服務(wù)器帶寬。
故使用Ajax定時(shí)刷新獲取最新數(shù)據(jù),兩種方案各有優(yōu)劣,根據(jù)實(shí)際場(chǎng)景進(jìn)行抉擇。
代碼如下:
1.Html頁(yè)面內(nèi)容(本人用的是Admin.lte的前端框架),
引入Datatable css 和 Js,并創(chuàng)建一個(gè)table:
<link rel="stylesheet" href="{% static '/plugins/bootstrap-datatable/bootstrap-table.css' %}" rel="external nofollow" >
<link rel="stylesheet" href="{% static '/bower_components/datatables.net-bs/css/dataTables.bootstrap.min.css' %}" rel="external nofollow" >
<table class="table table-bordered table-striped table-hover" id="monitorTable" style="width: 100%">
</table>
<script src="{% static '/bower_components/datatables.net/js/jquery.dataTables.min.js' %}"></script>
<script src="{% static '/bower_components/datatables.net-bs/js/dataTables.bootstrap.min.js' %}"></script>
2.頁(yè)面加載時(shí)本人對(duì)表格內(nèi)容進(jìn)行了初始化,下面的兩種方式對(duì)表格都能進(jìn)行初始化,但是獲取到的var 對(duì)象是不一樣的。
這里一定要注意(分不清楚就是個(gè)坑):
以var table1=$("#xxx").Datatable({})
以var table2=$("#xxx").datatable({})
即table1!=table2
這里要說(shuō)明下,上面的table1是對(duì)象,table2是API對(duì)象(請(qǐng)對(duì)這句話(huà)保持警惕),建議初始化表格時(shí)使用table1的方式。
根據(jù)官網(wǎng)的描述DataTables的真正威力可以通過(guò)使用它提供的API來(lái)利用。
關(guān)于table2的使用,以后會(huì)說(shuō)明?。?!
3.因?yàn)橥豁?yè)面可能使用多個(gè)表格,所以我要多個(gè)表格共用的部分提取出來(lái),避免代碼反復(fù)編寫(xiě):
下面的方法定義了3個(gè)參數(shù),
lengthMenuParam:table表格左上角的分頁(yè)列表“右側(cè)”需要顯示哪些內(nèi)容(這部分可以自定義)
urlParam:table中的數(shù)據(jù)從哪里獲取
columnsParam:table中有哪些列內(nèi)容
這里要注意下,bProcessing=True這個(gè)屬性很重要,這個(gè)屬性能很友好的提醒用戶(hù)數(shù)據(jù)正在讀取中,因?yàn)樽x取服務(wù)器數(shù)據(jù)是要時(shí)間的。
// table初始化方法
function initDataTable(lengthMenuParam, urlParam, columnsParam) {
return {
sPaginationType: "full_numbers", //分頁(yè)風(fēng)格,full_number會(huì)把所有頁(yè)碼顯示出來(lái)
searching: false,//搜索
ordering: false,//是否啟用排序
bProcessing: true, //是否顯示加載
sAjaxSource: urlParam, //請(qǐng)求資源路徑
serverSide: true, //開(kāi)啟服務(wù)器處理模式
/*
使用ajax,在服務(wù)端處理數(shù)據(jù)
sSource:即是"sAjaxSource"
aoData:要傳遞到服務(wù)端的參數(shù)
fnCallback:處理返回?cái)?shù)據(jù)的回調(diào)函數(shù)
*/
fnServerData: function (sSource, aoData, fnCallback) {
$.ajax({
'type': 'POST',
"url": sSource,
"dataType": "json",
"data": {"aodata": JSON.stringify(aoData)},
"success": function (resp) {
fnCallback(resp);
}
});
},
"oLanguage": {//語(yǔ)言設(shè)置
"sLengthMenu": '<select class="form-control" style="width:150px">'
+ '<option value="10" selected>每頁(yè)10條</option>'
+ '<option value="20">每頁(yè)20條</option>'
+ '<option value="50">每頁(yè)50條</option>'
+ '<option value="100">每頁(yè)100條</option>'
+ '</select>'
+ lengthMenuParam,,
"sProcessing": "處理中...",
"sZeroRecords": "沒(méi)有匹配結(jié)果",
"sInfo": "顯示第 _START_ 至 _END_ 項(xiàng)結(jié)果,共 _TOTAL_ 項(xiàng)",
"sInfoEmpty": "沒(méi)有數(shù)據(jù)",
"sInfoFiltered": "(獲取 _MAX_ 項(xiàng)結(jié)果)",
"sInfoPostFix": "",
"sSearch": "搜索:",
"sUrl": "",
"sEmptyTable": "表中數(shù)據(jù)為空",
"sLoadingRecords": "載入中...",
"sInfoThousands": ",",
"oPaginate": {
"sFirst": "首頁(yè)",
"sPrevious": "上頁(yè)",
"sNext": "下頁(yè)",
"sLast": "末頁(yè)"
},
},
"bProcessing": true, //開(kāi)啟讀取服務(wù)器數(shù)據(jù)時(shí)顯示正在加載中……特別是大數(shù)據(jù)量的時(shí)候,開(kāi)啟此功能比較好
"bServerSide": true, //開(kāi)啟服務(wù)器模式,使用服務(wù)器端處理配置datatable。
// 注意:sAjaxSource參數(shù)也必須被給予為了給datatable源代碼來(lái)獲取所需的數(shù)據(jù)對(duì)于每個(gè)畫(huà)。
// 這個(gè)翻譯有點(diǎn)別扭。開(kāi)啟此模式后,你對(duì)datatables的每個(gè)操作 每頁(yè)顯示多少條記錄、下一頁(yè)、上一頁(yè)、排序(表頭)、搜索,這些都會(huì)傳給服務(wù)器相應(yīng)的值。
"columns": columnsParam,
}
}
定義左側(cè)顯示參數(shù):
var lengthMenuParam =
'<div class="btn-group">' +
'<button type="button" class="btn btn-default" data-toggle="modal" data-target="#addResources_modal">添加</button>' +
'<button type="button" class="btn btn-default selectAllCheck">全選</button>' +
'<button type="button" class="btn btn-default" id="selectAllDelete">刪除</button>' +
'</div>';
定義url地址:
var urlParam = "{% url 'Monitor:monitor' %}";
定義列內(nèi)容:
var columnsParam = [
{title: "id", data: "id", sClass: "hidden"},
{
data: null,
sWidth: "1%",
'render': function (data, type, full, meta) {
return meta.row + 1 + meta.settings._iDisplayStart;
}
},
{
title: '<input type="checkbox" class="selectAllCheck">',
sWidth: "1%",
data: null,
'render': function (data, type, full, meta) {
return '<div><input type="checkbox"></div>';
}
},
{title: "名稱(chēng)", data: "name"},
{
title: "IP",
data: "ip",
"render": function (data, type, full, meta) {
var strDelete = '<a href="/docker/container?ip=' + data + '" rel="external nofollow" class="text-blue">' + data + '</a>';
return strDelete;
}
},
{title: "操作系統(tǒng)", data: "os"},
{title: "狀態(tài)", data: "status"},
{title: "創(chuàng)建日期", data: "createTime"},
{
data: null,
"render": function (data, type, full, meta) {
var strModify = "<button type='button' class='btn btn-warning btn-xs btn-flat modifyResources' data-toggle='modal' data-target='#modifyResources_modal'> <i class='fa fa-pencil'></i>修改</button > ";
var strDelete = "<button type='button' class='btn btn-danger btn-xs btn-flat deleteResources' > <i class='fa fa-pencil'></i>刪除</button > ";
return strModify + strDelete;
}
},
];
上面的列內(nèi)容中,第1列是隱藏內(nèi)容,第2列是行序號(hào),第3列check(用來(lái)多選的),
第4,6,7,8列是要顯示的信息,第5列是超鏈接。
第9列是操作按鈕(根據(jù)自己的選擇增加、刪除)。
一般情況下,上述內(nèi)容已經(jīng)夠用了。
4.完成表格的初始化:
$("#monitorTable").DataTable(
initDataTable(lengthMenuParam, urlParam, columnsParam)
)
注意,我這里的datatable分頁(yè)使用的是post請(qǐng)求, 因?yàn)榉猪?yè)的時(shí)候需要向服務(wù)端傳遞很多參數(shù),使用get請(qǐng)求的話(huà),這里就很難受了。
5.服務(wù)端代碼,返回結(jié)果的內(nèi)容格式是固定的,不要想著去修改:
@csrf_exempt
def monitor(request):
if request.method == 'GET':
return render(request, 'monitor/Monitor.html', )
else:
dataTable = {}
aodata = json.loads(request.POST.get("aodata"))
for item in aodata:
if item['name'] == "sEcho":
sEcho = int(item['value']) # 客戶(hù)端發(fā)送的標(biāo)識(shí)
if item['name'] == "iDisplayStart":
iDisplayStart = int(item['value']) # 起始索引
if item['name'] == "iDisplayLength":
iDisplayLength = int(item['value']) # 每頁(yè)顯示的行數(shù)
# 獲取最新的時(shí)間
last_time = T_Monitor.objects.order_by('-createTime').first().createTime
# 根據(jù)最新的時(shí)間獲取監(jiān)控?cái)?shù)據(jù)
monitor_list = T_Monitor.objects.filter(createTime=last_time).order_by('createTime')
#monitor_list = T_Monitor.objects.order_by('updateTime').all()
resultLength = monitor_list.count()
# 對(duì)list進(jìn)行分頁(yè)
paginator = Paginator(monitor_list, iDisplayLength)
# 把數(shù)據(jù)分成10個(gè)一頁(yè)。
try:
monitor_list = paginator.page(iDisplayStart / 10 + 1)
# 請(qǐng)求頁(yè)數(shù)錯(cuò)誤
except PageNotAnInteger:
monitor_list = paginator.page(1)
except EmptyPage:
monitor_list = paginator.page(paginator.num_pages)
data=[]
for item in monitor_list:
row = {"id": str(item.id),
"name": item.name,
"ip": item.ip,
"os": item.os[0:6],
"status": item.status,
"createTime": item.createTime.strftime('%Y-%m-%d %H:%M:%S')}
data.append(row)
#對(duì)最終的數(shù)據(jù)進(jìn)行排序
data = sorted(data, key=lambda item: item['createTime'])
dataTable['iTotalRecords'] = resultLength # 數(shù)據(jù)總條數(shù)
dataTable['sEcho'] = sEcho + 1
dataTable['iTotalDisplayRecords'] = resultLength # 顯示的條數(shù)
dataTable['aaData'] = data
return HttpResponse(json.dumps(dataTable, ensure_ascii=False))
最終的表現(xiàn)結(jié)果如下圖:

6.添加定時(shí)刷新table的JS
<script>
//刷新方法
function runRefresh() {
var interval = setInterval(refreshMonitor, "5000");
}
{#定時(shí)器運(yùn)行方法#}
function refreshMonitor() {
var table = $('#monitorTable').DataTable();
table.ajax.reload(null, false); // 刷新表格數(shù)據(jù),分頁(yè)信息不會(huì)重置
}
runRefresh();
</script>
最后強(qiáng)調(diào)一點(diǎn),table數(shù)據(jù)也是可以通過(guò)get請(qǐng)求進(jìn)行加載的。
但是使用了get方式后,在某頁(yè)進(jìn)行操作再進(jìn)行上面的JS刷新時(shí)會(huì)出現(xiàn)行序號(hào)紊亂或者分頁(yè)信息被重置的問(wèn)題。
這也是我碰到的一個(gè)坑。
特此記錄一下。
補(bǔ)充知識(shí):關(guān)于python的web框架django和Bootstrap-table的使用
這幾天工作中發(fā)現(xiàn)要使用到Bootstrap的分頁(yè),django也有分頁(yè),但是當(dāng)兩者結(jié)合起來(lái)時(shí)發(fā)現(xiàn),是一個(gè)強(qiáng)大的分頁(yè)。
第一次接觸這兩者,結(jié)合起來(lái)時(shí)踩了不少坑,因?yàn)樽约菏且粋€(gè)python初學(xué)者,以前是學(xué)的Java,在公司做的python。
自己在網(wǎng)上找到一些資料,但發(fā)現(xiàn)這些資料都說(shuō)的不明白,所以自己也去看了文檔。
我把自己的代碼貼出來(lái)吧。
這個(gè)方法是將你的數(shù)據(jù)跟據(jù)你的頁(yè)碼,頁(yè)面大小,分好頁(yè)
def page(deploy_list ,limit,offset):#查詢(xún)分頁(yè),調(diào)用此方法需要傳獲取的數(shù)據(jù)列表,頁(yè)面大小,頁(yè)碼
# 取出該表所有數(shù)據(jù)
try:
paginator = Paginator(deploy_list, limit) # 每頁(yè)顯示10條數(shù)據(jù)
except Exception:
print "error"
page = int(int(offset) / int(limit) + 1)
data=paginator.page(page)
response_data = {'total': deploy_list.count(), 'rows': []} # 必須帶有rows和total這2個(gè)key,total表示總頁(yè)數(shù),rows表示每行的內(nèi)容,這兩個(gè)是Bootstrap需要的
return {"data":data,"response_data":response_data}
調(diào)用上述方法時(shí)將自己需要的數(shù)據(jù)獲取到
def list(request):
J_data=page(modename.object.all().values(),request.GET.get("limit"),request.GET.get("offset"))#modelname,這個(gè)是你需要查詢(xún)的model,modename.object.all().values(),這個(gè)可以根據(jù)自己的查詢(xún)條件去更改,例如:modename.object.filter(username=requset.GET.get("username")).values()
for asset in J_data:
J_data['response_data']['youmodel ziduan '].append({
"asset_id":asset["asset_id"],"asset_id":asset["asset_id"],
})
return HttpResponse(json.dumps(J_data["response_data"])) # 需要json處理下數(shù)據(jù)格式
前臺(tái)代碼百度很多,可以自己去寫(xiě) ,這里就不再陳述

以上這篇DjangoWeb使用Datatable進(jìn)行后端分頁(yè)的實(shí)現(xiàn)就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python?Pandas聚合函數(shù)的應(yīng)用示例
Pandas是當(dāng)前Python數(shù)據(jù)分析中最為重要的工具,其提供了功能強(qiáng)大且靈活多樣的API,可以滿(mǎn)足使用者在數(shù)據(jù)分析和處理中的多種選擇和實(shí)現(xiàn)方式,下面這篇文章主要給大家介紹了關(guān)于Python?Pandas聚合函數(shù)的相關(guān)資料,需要的朋友可以參考下2022-07-07
python中關(guān)于range()函數(shù)反向遍歷的幾種表達(dá)
這篇文章主要介紹了python中關(guān)于range()函數(shù)反向遍歷的幾種表達(dá),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05
python opencv 檢測(cè)移動(dòng)物體并截圖保存實(shí)例
這篇文章主要介紹了python opencv 檢測(cè)移動(dòng)物體并截圖保存實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-03-03
解決pip install中UnicodeDecodeError問(wèn)題的處理
這篇文章主要介紹了解決pip install中UnicodeDecodeError問(wèn)題的處理,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-09-09
Python 用三行代碼提取PDF表格數(shù)據(jù)
這篇文章主要介紹了Python 用三行代碼提取PDF表格數(shù)據(jù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
python爬蟲(chóng)入門(mén)教程--優(yōu)雅的HTTP庫(kù)requests(二)
requests 實(shí)現(xiàn)了 HTTP 協(xié)議中絕大部分功能,它提供的功能包括 Keep-Alive、連接池、Cookie持久化、內(nèi)容自動(dòng)解壓、HTTP代理、SSL認(rèn)證等很多特性,下面這篇文章主要給大家介紹了python爬蟲(chóng)入門(mén)中關(guān)于優(yōu)雅的HTTP庫(kù)requests的相關(guān)資料,需要的朋友可以參考下。2017-05-05
使用flask如何獲取post請(qǐng)求參數(shù)
近日在使用flask框架獲取前端的請(qǐng)求時(shí)獲取參數(shù)時(shí),遇到了幾個(gè)問(wèn)題,所以下面這篇文章主要給大家介紹了關(guān)于使用flask如何獲取post請(qǐng)求參數(shù)的相關(guān)資料,需要的朋友可以參考下2022-08-08
Python多維/嵌套字典數(shù)據(jù)無(wú)限遍歷的實(shí)現(xiàn)
下面小編就為大家?guī)?lái)一篇Python多維/嵌套字典數(shù)據(jù)無(wú)限遍歷的實(shí)現(xiàn)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-11-11

