1. 程式人生 > 程式設計 >DjangoWeb使用Datatable進行後端分頁的實現

DjangoWeb使用Datatable進行後端分頁的實現

使用場景:不使用Django的模版語言進行分頁(網上大多數都使用該方式),使用Jquery DataTable.js 外掛進行分頁處理。

本人做的是一個表格監控頁面,該頁面中的table內容每5s重新整理一次。

注意:這種方式非長連線(websocket)模式,長連線模式也有弊端,因網路波動導致,倘若一次連線斷開,後面將無法繼續重新整理資料(不重連的話),且比較吃伺服器頻寬。

故使用Ajax定時重新整理獲取最新資料,兩種方案各有優劣,根據實際場景進行抉擇。

程式碼如下:

1.Html頁面內容(本人用的是Admin.lte的前端框架),

引入Datatable css 和 Js,並建立一個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.頁面載入時本人對錶格內容進行了初始化,下面的兩種方式對錶格都能進行初始化,但是獲取到的var 物件是不一樣的。

這裡一定要注意(分不清楚就是個坑):

以var table1=$("#xxx").Datatable({})

以var table2=$("#xxx").datatable({})

即table1!=table2

這裡要說明下,上面的table1是物件,table2是API物件(請對這句話保持警惕),建議初始化表格時使用table1的方式。

根據官網的描述DataTables的真正威力可以通過使用它提供的API來利用。

關於table2的使用,以後會說明!!!

3.因為同一頁面可能使用多個表格,所以我要多個表格共用的部分提取出來,避免程式碼反覆編寫:

下面的方法定義了3個引數,

lengthMenuParam:table表格左上角的分頁列表“右側”需要顯示哪些內容(這部分可以自定義)

urlParam:table中的資料從哪裡獲取

columnsParam:table中有哪些列內容

這裡要注意下,bProcessing=True這個屬性很重要,這個屬效能很友好的提醒使用者資料正在讀取中,因為讀取伺服器資料是要時間的。

// table初始化方法
function initDataTable(lengthMenuParam,urlParam,columnsParam) {
 return {
   sPaginationType: "full_numbers",//分頁風格,full_number會把所有頁碼顯示出來
   searching: false,//搜尋
   ordering: false,//是否啟用排序
   bProcessing: true,//是否顯示載入
   sAjaxSource: urlParam,//請求資源路徑
   serverSide: true,//開啟伺服器處理模式
   /*
    使用ajax,在服務端處理資料
    sSource:即是"sAjaxSource"
    aoData:要傳遞到服務端的引數
    fnCallback:處理返回資料的回撥函式
    */
   fnServerData: function (sSource,aoData,fnCallback) {
    $.ajax({
     'type': 'POST',"url": sSource,"dataType": "json","data": {"aodata": JSON.stringify(aoData)},"success": function (resp) {
      fnCallback(resp);
     }
    });
   },"oLanguage": {//語言設定
    "sLengthMenu": '<select class="form-control" style="width:150px">'
    + '<option value="10" selected>每頁10條</option>'
    + '<option value="20">每頁20條</option>'
    + '<option value="50">每頁50條</option>'
    + '<option value="100">每頁100條</option>'
    + '</select>'
 + lengthMenuParam,"sProcessing": "處理中...","sZeroRecords": "沒有匹配結果","sInfo": "顯示第 _START_ 至 _END_ 項結果,共 _TOTAL_ 項","sInfoEmpty": "沒有資料","sInfoFiltered": "(獲取 _MAX_ 項結果)","sInfoPostFix": "","sSearch": "搜尋:","sUrl": "","sEmptyTable": "表中資料為空","sLoadingRecords": "載入中...","sInfoThousands": ",","oPaginate": {
     "sFirst": "首頁","sPrevious": "上頁","sNext": "下頁","sLast": "末頁"
    },},"bProcessing": true,//開啟讀取伺服器資料時顯示正在載入中……特別是大資料量的時候,開啟此功能比較好
   "bServerSide": true,//開啟伺服器模式,使用伺服器端處理配置datatable。
   // 注意:sAjaxSource引數也必須被給予為了給datatable原始碼來獲取所需的資料對於每個畫。
   // 這個翻譯有點彆扭。開啟此模式後,你對datatables的每個操作 每頁顯示多少條記錄、下一頁、上一頁、排序(表頭)、搜尋,這些都會傳給伺服器相應的值。
   "columns": columnsParam,}
}

定義左側顯示引數:

   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' %}";

定義列內容:

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">',data: null,meta) {
      return '<div><input type="checkbox"></div>';
     }
    },{title: "名稱",data: "name"},{
     title: "IP",data: "ip","render": function (data,meta) {
      var strDelete = '<a href="/docker/container?ip=' + data + '" rel="external nofollow" class="text-blue">' + data + '</a>';
      return strDelete;
     }
    },{title: "作業系統",data: "os"},{title: "狀態",data: "status"},{title: "建立日期",data: "createTime"},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;
     }
    },];

上面的列內容中,第1列是隱藏內容,第2列是行序號,第3列check(用來多選的),

第4,6,7,8列是要顯示的資訊,第5列是超連結。

第9列是操作按鈕(根據自己的選擇增加、刪除)。

一般情況下,上述內容已經夠用了。

4.完成表格的初始化:

   $("#monitorTable").DataTable(
    initDataTable(lengthMenuParam,columnsParam)
   )

注意,我這裡的datatable分頁使用的是post請求, 因為分頁的時候需要向服務端傳遞很多引數,使用get請求的話,這裡就很難受了。

5.服務端程式碼,返回結果的內容格式是固定的,不要想著去修改:

@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']) # 客戶端傳送的標識
   if item['name'] == "iDisplayStart":
    iDisplayStart = int(item['value']) # 起始索引
   if item['name'] == "iDisplayLength":
    iDisplayLength = int(item['value']) # 每頁顯示的行數
  # 獲取最新的時間
  last_time = T_Monitor.objects.order_by('-createTime').first().createTime
  # 根據最新的時間獲取監控資料
  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()
  # 對list進行分頁
  paginator = Paginator(monitor_list,iDisplayLength)
  # 把資料分成10個一頁。
  try:
   monitor_list = paginator.page(iDisplayStart / 10 + 1)
  # 請求頁數錯誤
  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)
  #對最終的資料進行排序
  data = sorted(data,key=lambda item: item['createTime'])
  dataTable['iTotalRecords'] = resultLength # 資料總條數
  dataTable['sEcho'] = sEcho + 1
  dataTable['iTotalDisplayRecords'] = resultLength # 顯示的條數
  dataTable['aaData'] = data
 
  return HttpResponse(json.dumps(dataTable,ensure_ascii=False))

最終的表現結果如下圖:

DjangoWeb使用Datatable進行後端分頁的實現

6.新增定時重新整理table的JS

 <script>
 
  //重新整理方法
  function runRefresh() {
   var interval = setInterval(refreshMonitor,"5000");
  }
  {#定時器執行方法#}
  function refreshMonitor() {
   var table = $('#monitorTable').DataTable();
   table.ajax.reload(null,false); // 重新整理表格資料,分頁資訊不會重置
  }
  runRefresh();
 </script>

最後強調一點,table資料也是可以通過get請求進行載入的。

但是使用了get方式後,在某頁進行操作再進行上面的JS重新整理時會出現行序號紊亂或者分頁資訊被重置的問題。

這也是我碰到的一個坑。

特此記錄一下。

補充知識:關於python的web框架django和Bootstrap-table的使用

這幾天工作中發現要使用到Bootstrap的分頁,django也有分頁,但是當兩者結合起來時發現,是一個強大的分頁。

第一次接觸這兩者,結合起來時踩了不少坑,因為自己是一個python初學者,以前是學的Java,在公司做的python。

自己在網上找到一些資料,但發現這些資料都說的不明白,所以自己也去看了文件。

我把自己的程式碼貼出來吧。

這個方法是將你的資料跟據你的頁碼,頁面大小,分好頁

def page(deploy_list,limit,offset):#查詢分頁,呼叫此方法需要傳獲取的資料列表,頁面大小,頁碼
  # 取出該表所有資料
 try:
  paginator = Paginator(deploy_list,limit) # 每頁顯示10條資料
 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個key,total表示總頁數,rows表示每行的內容,這兩個是Bootstrap需要的
 return {"data":data,"response_data":response_data}

呼叫上述方法時將自己需要的資料獲取到

def list(request):
 J_data=page(modename.object.all().values(),request.GET.get("limit"),request.GET.get("offset"))#modelname,這個是你需要查詢的model,modename.object.all().values(),這個可以根據自己的查詢條件去更改,例如: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處理下資料格式 

前臺程式碼百度很多,可以自己去寫 ,這裡就不再陳述

DjangoWeb使用Datatable進行後端分頁的實現

以上這篇DjangoWeb使用Datatable進行後端分頁的實現就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。