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">',
     sWidth: "1%",
     data: null,
     'render': function (data, type, full, meta) {
      return '<div><input type="checkbox"></div>';
     }
    },
    {title: "名称", 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: "操作系统", data: "os"},
    {title: "状态", data: "status"},
    {title: "创建日期", 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;
     }
    },
   ];

上面的列内容中,第1列是隐藏内容,第2列是行序号,第3列check(用来多选的),

第4,6,7,8列是要显示的信息,第5列是超链接。

第9列是操作按钮(根据自己的选择增加、删除)。

一般情况下,上述内容已经够用了。

4.完成表格的初始化:

   $("#monitorTable").DataTable(
    initDataTable(lengthMenuParam, urlParam, 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))

最终的表现结果如下图:

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进行后端分页的实现就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Python Django 简单分页的实现代码解析

    这篇文章主要介绍了Python Django 简单分页的实现代码解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 models.py: from django.db import models class Book(models.Model): title = models.CharField(max_length=32) def __str__(self): return self.title class Meta: db_table =

  • Django实现基于类的分页功能

    开发个人博客时往往避免不了分页功能的实现,实现方法大体上分为函数和类两种.本文基于类实现分页功能,以下是详细代码: class Page: page_num = 0 total_count = 0 tartype = "" total_page = 0 # 总页数 per_page = 8 # 每页显示8篇文章 max_page = 11 # 每页最大展示页数选项 half_page = max_page // 2 category = "" # 标记该链接所属分类

  • Django实现分页显示效果

    Django中提供了一个类Paginator专门用来管理和处理分页数据,所以我们在使用之前先导入好相应的类,,另外这里我们也导入了待会会用到的处理异常的两个类 EmptyPage和PageNotAnInteger: from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger 接着编写好视图函数test: def test(request): course_list=CourseVideo.objects.all

  • 如何在django中实现分页功能

    1.在html页面中导入js文件和css文件 <link rel="stylesheet" href="../../../static/css/jquery.pagination.css" rel="external nofollow" > <script type="text/javascript" src="../../../static/js/jquery-1.12.4.min.js"

  • DjangoWeb使用Datatable进行后端分页的实现

    使用场景:不使用Django的模版语言进行分页(网上大多数都使用该方式),使用Jquery DataTable.js 插件进行分页处理. 本人做的是一个表格监控页面,该页面中的table内容每5s刷新一次. 注意:这种方式非长连接(websocket)模式,长连接模式也有弊端,因网络波动导致,倘若一次连接断开,后面将无法继续刷新数据(不重连的话),且比较吃服务器带宽. 故使用Ajax定时刷新获取最新数据,两种方案各有优劣,根据实际场景进行抉择. 代码如下: 1.Html页面内容(本人用的是Adm

  • Bootstrap table学习笔记(2) 前后端分页模糊查询

    在使用过程中,一边看文档一边做,遇到了一些困难的地方,在此记录一下,顺便做个总结: 1.前端分页 2.后端分页 3.模糊查询 前端分页相当简单,在我添加了2w条测试数据的时候打开的很流畅,没有卡顿. $(function(){ a(); }); function a () { $('#yourtable').bootstrapTable({ url: "/user/getUserList/", method:"post", dataType: "json&

  • laypage+SpringMVC实现后端分页

    项目中用到了模板引擎thymeleaf和前端框架layUI,算是一路摸索.一个坑一个坑踩过来的.之前边学习边做项目的时候没有记录下学习的过程和遇到问题的解决思路和方法,着实有点可惜.所以从现在开始咯. laypage分页 下面就以laypage的两种分页展开行文的思路:异步刷新分页和整页刷新式跳转.具体可参看官方文档. 异步刷新分页 首先使用laypage之前,先加载laypage模块.使用 layui.use('laypage')加载即可. 1.前端html代码如下: <div id="

  • layUI实现前端分页和后端分页

    本文实例为大家分享了layUI实现前端分页和后端分页效果,供大家参考,具体内容如下 layui后端分页: function pagination(curr,gwayId,mlity,ePart) { $(".manage_ys_list").html('加载中...'); let dd={ conditions: { gatewayId:gwayId, searchText:"", pageSize:15, pageIndex:curr-1 }, identity:

  • bootstrap-table后端分页功能完整实例

    本文实例讲述了bootstrap-table后端分页功能.分享给大家供大家参考,具体如下: 使用bootstrap-table实现后台分页 插件资源点击此处本站下载. 引用以下css <link rel="stylesheet" href="../plugins/bootstrap/css/bootstrap.min.css" rel="external nofollow" > <link rel="styleshee

  • idea使用pagehelper实现后端分页功能的步骤详解

    PageHelper是一款好用的开源免费的Mybatis第三方物理分页插件,其实我并不想加上好用两个字,但是为了表扬插件作者开源免费的崇高精神,我毫不犹豫的加上了好用一词作为赞美. 下面分步骤给大家介绍idea使用pagehelper实现后端分页功能,具体内容如下所示: 第一步:在pom.xml中添加依赖 <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-

  • 一篇文章告诉你如何实现Vue前端分页和后端分页

    目录 1:前端手写分页(数据量小的情况下) 2:后端分页,前端只需要关注传递的page和pageSize 总结 1:前端手写分页(数据量小的情况下) 前端需要使用slice截取: tableData((page-1)pageSize,pagepageSize) 2:后端分页,前端只需要关注传递的page和pageSize 3:前端手写分页按钮 <body> <div id="app"> <table class="table table-bord

  • jquery datatable服务端分页

    OK,上次完成了客户端的分页,这次我们就在上一次的Demo上进行修改,来实现服务端的分页~ js代码: <script type="text/javascript"> $(document).ready(function() { $('#table_id_example').DataTable({ "bProcessing" : false, //是否显示加载 "sAjaxSource" : '/datatableDemo/user/

  • jquery dataTable 后台加载数据并分页实例代码

    使用 dataTable后台加载数据并分页.网上版本很多,但很多都是不能用或者不详细的,这里是已经验证过的. 引用 js文件 <script src="static/ace/js/jquery-2.0.3.min.js"></script> <script src="static/ace/js/jquery.dataTables.min.js"></script> <script src="static

  • jQuery DataTables插件自定义Ajax分页实例解析

    一.问题描述 园友是做前端的,产品经理要求他使用jQuery DataTables插件显示一个列表,要实现分类效果. 后端的分页接口已经写好了,不涉及条件查询,需要传入页码(pageNo)和页面显示数据条数(pageSize),显示相应页的显示记录,且不能修改后端接口. 二.分析 先来分析下分页实现. 一是后端分页:这种情况下,在后端很容易实现,在官网上有示例,不多说明. 二是前端分页:前端分页也是支持的,不过需要一次把所有数据都获取到才可以. 看到这里,问题来了.由于后端在目前的情况下是更改不

随机推荐