您的位置:首页技术文章
文章详情页

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

【字号: 日期:2024-10-05 11:52:59浏览:35作者:猪猪

使用场景:不使用Django的模版语言进行分页(网上大多数都使用该方式),使用Jquery DataTable.js 插件进行分页处理。

本人做的是一个表格监控页面,该页面中的table内容每5s刷新一次。

注意:这种方式非长连接(websocket)模式,长连接模式也有弊端,因网络波动导致,倘若一次连接断开,后面将无法继续刷新数据(不重连的话),且比较吃服务器带宽。

故使用Ajax定时刷新获取最新数据,两种方案各有优劣,根据实际场景进行抉择。

代码如下:

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

引入Datatable css 和 Js,并创建一个table:

<link rel='stylesheet' href='https://www.haobala.com/bcjs/{% static ’/plugins/bootstrap-datatable/bootstrap-table.css’ %}' rel='external nofollow' ><link rel='stylesheet' href='https://www.haobala.com/bcjs/{% static ’/bower_components/datatables.net-bs/css/dataTables.bootstrap.min.css’ %}' rel='external nofollow' > <table style='width: 100%'></table><script src='https://www.haobala.com/bcjs/{% static ’/bower_components/datatables.net/js/jquery.dataTables.min.js’ %}'></script><script src='https://www.haobala.com/bcjs/{% 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 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' data-toggle='modal' data-target='#addResources_modal'>添加</button>’ + ’<button type='button' class='btn btn-default selectAllCheck'>全选</button>’ + ’<button type='button' 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='https://www.haobala.com/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_exemptdef 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进行后端分页的实现就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持好吧啦网。

标签: Django
相关文章: