datatables后端分页

0x01 缘由



平时较少涉及前端,这次本以为模板中有表单,分页跳转搜索功能都比较齐全,可以高枕无忧,但是细看模板中的分页跳转是不需要与后台交互的,数据一次性写在前端,再有前端插件完成分页。

这种方式肯定是不可行的,这次要做的可以看做资产管理,服务器+主机量级很大,一个机器生成一条 <th>,第一次请求的前端代码怕是要崩掉。

所以合理采用的还是后端分页

0x02 分页方式



团队项目里看过的几种后端分页方式:

1. Paginator + render渲染整个页面,这种方式比较好理解,但是每一次跳转分页,都会替换掉整块main-content部分。

2. datatables 后端分页,这种方式按照datatables提供的API填写相关信息与逻辑,缺点是

  1) 受限于这种插件的条条框框,要自定义一些内容有点麻烦。

    比如原始datatables中search是实时的,即在search input框中输入 "123",会进行 "1"、"12"、"123"三次过滤,在后端分页中,就会发起三次查询。

    所以要自定义搜索,但是form部分是由datatables初始化过程中生成的,找半天没有找到插入自定义<input>框的接口。所以用jquery遍历再添加 <input>。

  2) 文档不太清晰

    各种API、接口,在文档中找来找去挺麻烦的。等到整块写的差不多的时候,才意外看到官方后端分页的文档。

3. 自己编写form、跳转、查询、排序、每页数量等功能,就是稍显麻烦,但还是挺灵活的。

0x03 datatables后端分页流程



由于模板本身的表单是基于datatables的,所以最后还是修改了datatables。

datatables后端分页的流程大概可以分为四部分:

1. 修改datatables的初始化参数,改为后端分页,并修改其他设置

2. datatables传递数据给服务端

3. 接收服务端数据,比如说取到第10页的10条json数据

4. 数据渲染至datatables当前页面

0x04 修改datatables初始化参数


<script type="text/javascript">
    $(function () {
        //提示信息
        var lang = {
            "sProcessing": "处理中...",
            "sLengthMenu": "每页 _MENU_ 项",
            "sZeroRecords": "没有匹配结果",
            "sInfo": "当前显示第 _START_ 至 _END_ 项,共 _TOTAL_ 项。",
            "sInfoEmpty": "当前显示第 0 至 0 项,共 0 项",
            "sInfoFiltered": "(由 _MAX_ 项结果过滤)",
            "sInfoPostFix": "",
            "sSearch": "搜索:",
            "sUrl": "",
            "sEmptyTable": "表中数据为空",
            "sLoadingRecords": "载入中...",
            "sInfoThousands": ",",
            "oPaginate": {
                "sFirst": "首页",
                "sPrevious": "上页",
                "sNext": "下页",
                "sLast": "末页",
                "sJump": "跳转"
            },
            "oAria": {
                "sSortAscending": ": 以升序排列此列",
                "sSortDescending": ": 以降序排列此列"
            }
        };

        //初始化表格
        var table = $("#dynamic-table").dataTable({
            language:lang,  //提示信息
            autoWidth: false,  //禁用自动调整列宽
            stripeClasses: ["odd", "even"],  //为奇偶行加上样式,兼容不支持CSS伪类的场合
            processing: true,  //隐藏加载提示,自行处理
            serverSide: true,  //启用服务器端分页
            searching: false,  //禁用原生搜索
            orderMulti: false,  //启用多列排序
            order: [],  //取消默认排序查询,否则复选框一列会出现小箭头
            renderer: "bootstrap",  //渲染样式:Bootstrap和jquery-ui
            pagingType: "simple_numbers",  //分页样式:simple,simple_numbers,full,full_numbers
            columnDefs: [{
                "targets": ‘nosort‘,  //列的样式名
                "orderable": false    //包含上样式名‘nosort’的禁止排序
            }]
        }).api();//此处需调用api()方法,否则返回的是JQuery对象而不是DataTables的API对象
    });
</script>

datatables初始化中,以字典的形式将初始化信息传递进去。

其中,language为表单的一些提示信息。这里比较简单,基本上看看就明白。

所以,现在表单已经初始化成了后端模式了。

接下来,怎么给后端传递数据

0x05 前后端数据交互



需要增加的两个值:ajax 与 column

<script type="text/javascript">
    $(function () {
        //提示信息
        var lang = {
            "sProcessing": "处理中...",
            "sLengthMenu": "每页 _MENU_ 项",
            "sZeroRecords": "没有匹配结果",
            "sInfo": "当前显示第 _START_ 至 _END_ 项,共 _TOTAL_ 项。",
            "sInfoEmpty": "当前显示第 0 至 0 项,共 0 项",
            "sInfoFiltered": "(由 _MAX_ 项结果过滤)",
            "sInfoPostFix": "",
            "sSearch": "搜索:",
            "sUrl": "",
            "sEmptyTable": "表中数据为空",
            "sLoadingRecords": "载入中...",
            "sInfoThousands": ",",
            "oPaginate": {
                "sFirst": "首页",
                "sPrevious": "上页",
                "sNext": "下页",
                "sLast": "末页",
                "sJump": "跳转"
            },
            "oAria": {
                "sSortAscending": ": 以升序排列此列",
                "sSortDescending": ": 以降序排列此列"
            }
        };

        //初始化表格
        var table = $("#dynamic-table").dataTable({
            language:lang,  //提示信息
            autoWidth: false,  //禁用自动调整列宽
            stripeClasses: ["odd", "even"],  //为奇偶行加上样式,兼容不支持CSS伪类的场合
            processing: true,  //隐藏加载提示,自行处理
            serverSide: true,  //启用服务器端分页
            searching: false,  //禁用原生搜索
            orderMulti: false,  //启用多列排序
            order: [],  //取消默认排序查询,否则复选框一列会出现小箭头
            renderer: "bootstrap",  //渲染样式:Bootstrap和jquery-ui
            pagingType: "simple_numbers",  //分页样式:simple,simple_numbers,full,full_numbers
            columnDefs: [{
                "targets": ‘nosort‘,  //列的样式名
                "orderable": false    //包含上样式名‘nosort’的禁止排序
            }],
            ajax: function (data, callback, settings) {
                //封装请求参数
                console.log(data);
                var param = {};
                param.limit = data.length;//页面显示记录条数,在页面显示每页显示多少项的时候
                param.start = data.start;//开始的记录序号
                param.page = (data.start / data.length)+1;//当前页码
                param.order = data.order[0]
                //console.log(param);
                //ajax请求数据
                $.ajax({
                    type: "GET",
                    url: "http://your_server",
                    cache: false,  //禁用缓存
                    data: param,  //传入组装的参数
                    dataType: "json",
                    success: function (result) {
                        console.log(result);
                        //setTimeout仅为测试延迟效果
                        setTimeout(function () {
                            //封装返回数据
                            var returnData = {};
                            returnData.draw = data.draw;//这里直接自行返回了draw计数器,应该由后台返回
                            returnData.recordsTotal = result.total;//返回数据全部记录
                            returnData.recordsFiltered = result.total;//后台不实现过滤功能,每次查询均视作全部结果
                            returnData.data = result.data;//返回的数据列表
                            //console.log(returnData);
                            //调用DataTables提供的callback方法,代表数据已封装完成并传回DataTables进行渲染
                            //此时的数据需确保正确无误,异常判断应在执行此回调前自行处理完毕
                            callback(returnData);
                        }, 200);
                    }
                });
            },
            //列表表头字段
            columns: [
                { "data": "ip" },
                { "data": "online_state" },
                { "data": "machine_id" },
                { "data": "location" },
                { "data": "agent_state" },
                { "data": "system" }
            ]
        }).api();//此处需调用api()方法,否则返回的是JQuery对象而不是DataTables的API对象
    });
</script>

1. ajax: function(data,callback,settings){}——data

data为datatables本身会提供的数据集合,包含每一列的信息、一页的数据量(一页几行)、查找的值、当前页等,另外根据datatables的初始化选择还会包含其他内容,比如,当点击排序时,data中将包含排序的列、方式。

想要传递给服务端的数据,可以在这一处取。但是最好将数据重新封装一遍再发送给服务器,原因是:

  1) 有的数据是不需要的,比如在原生搜索关闭的情况下,data中还是会以后search的信息

  2) 有一些自定义的信息,比如自定义搜索框,可以封装入其中再传给服务器

  3) 整理格式,比如 排序数据 order中, order[0] 包含排序的列和方式,其他没什么用,所以取出order[0] 封装再发送,简洁得多。

数据封装完毕,则采用ajax的方式将数据发送给服务端。

2. ajax: function(data,callback,settings){}——callback

callback为返回给datatables渲染当前表单的数据,以字典形式。

其中,draw与data中的draw相同。

recordsTotal、recordsFiltered填写为数据库总数据量即可,datatables从中获取数据总量、分页数量等。

渲染的核心数据 data,是给表单渲染内容用的。

3. columns字段

columns字段的作用是:

将回调函数中的data中的数据,按columns的排序渲染入表单列中,比如这里,第一列为ip,则将data[‘ip‘] 放到第一列中,以此类推。

4. 后端返回什么数据

后端的数据可以根据传递给回调函数的数据进行猜测拼接,但是data也是字典格式的,返回的数据用Python可以写为:

data = [
    {‘ip‘:‘192.168.1.91‘,‘online_state‘:‘运行中‘,‘machine_id‘:‘91‘,‘location‘:‘58security‘,‘agent_state‘:‘OK‘,‘system‘:‘windows‘},
    {‘ip‘:‘192.168.1.92‘,‘online_state‘:‘运行中‘,‘machine_id‘:‘92‘,‘location‘:‘58security‘,‘agent_state‘:‘OK‘,‘system‘:‘windows‘},
    {‘ip‘:‘192.168.1.93‘,‘online_state‘:‘运行中‘,‘machine_id‘:‘93‘,‘location‘:‘58security‘,‘agent_state‘:‘OK‘,‘system‘:‘windows‘},
    {‘ip‘:‘192.168.1.94‘,‘online_state‘:‘运行中‘,‘machine_id‘:‘94‘,‘location‘:‘58security‘,‘agent_state‘:‘OK‘,‘system‘:‘windows‘},
    {‘ip‘:‘192.168.1.95‘,‘online_state‘:‘运行中‘,‘machine_id‘:‘95‘,‘location‘:‘58security‘,‘agent_state‘:‘OK‘,‘system‘:‘windows‘},
    {‘ip‘:‘192.168.1.96‘,‘online_state‘:‘运行中‘,‘machine_id‘:‘96‘,‘location‘:‘58security‘,‘agent_state‘:‘OK‘,‘system‘:‘windows‘},
    {‘ip‘:‘192.168.1.97‘,‘online_state‘:‘运行中‘,‘machine_id‘:‘97‘,‘location‘:‘58security‘,‘agent_state‘:‘OK‘,‘system‘:‘windows‘},
    {‘ip‘:‘192.168.1.98‘,‘online_state‘:‘运行中‘,‘machine_id‘:‘98‘,‘location‘:‘58security‘,‘agent_state‘:‘OK‘,‘system‘:‘windows‘},
    {‘ip‘:‘192.168.1.99‘,‘online_state‘:‘运行中‘,‘machine_id‘:‘99‘,‘location‘:‘58security‘,‘agent_state‘:‘OK‘,‘system‘:‘windows‘},
    {‘ip‘:‘192.168.1.100‘,‘online_state‘:‘运行中‘,‘machine_id‘:‘100‘,‘location‘:‘58security‘,‘agent_state‘:‘OK‘,‘system‘:‘windows‘},
]
response = {‘data‘:data,‘limit‘:10,‘page‘:10,‘total‘:100}
return JsonResponse(response)

在 ajax success中接收这些数据,再进行封装、传入datatables回调函数,从而完成渲染。

其中,显而易见,data以 “字段”:"内容"的形式存在于字典中。

5. 自定义搜索

由此,基本已经完成。

但是原生的搜索是不能用了,所以要自定义搜索。

也找不到添加 <input>框的接口,所以,用jquery遍历搜索再添加<input>元素、绑定事件。

绑定的事件要做什么事呢?

最简单的就是让datatables执行一次提交ajax,这里使用 datatables对象的draw()函数。

function search(){
    table.draw();
}
var search_input = "<div class=\"dataTables_filter\"><div class=\"span6\"><input id=\"search_key\"></input><button type=\"button\" id=\"search_button\" >搜索</button></div></div>";
$("#dynamic-table_wrapper").find(".row").first().find(".col-sm-6").last().append(search_input);
$("#search_button").click(function(){
    search();
});
$("#search_key").keydown(function(e){
    if(e.keyCode == 13){
        search();
    }
})

在初始化结束后,加入这段:遍历、添加元素、绑定事件、事件为datatables发出ajax。

draw()默认参数为true,表明刷新时会跳转到第一页重新刷新;draw(false) 则保持在原页。

同时,搜索的值也要传递给服务端:在封装数据时加入

param.search_key = $("#search_key").val()

参考——重要程度由高到低:

1. datatables服务端处理-可作后端分页文档

2. 引导我做demo的文章 jQuery Data Tables 插件自定义Ajax分页实现

一脸懵时可以做一个demo,后端数据返回,form完成,再一步步做转移。

3. 自行封装请求和返回数据的零耦合服务端分页

4. 官方文档 datatables Ajax

5. dataTables-使用详细说明

原文地址:https://www.cnblogs.com/huim/p/9514337.html

时间: 2024-10-31 00:43:59

datatables后端分页的相关文章

更改datatables的分页切换时的&#39;processing&#39;提示信息的式样

jquery.dataTables.css .dataTables_wrapper .dataTables_processing { position: absolute; top: 50%; left: 50%; /* width: 100%; */ width: 100px height: 40px; margin-left: -50%; margin-left: auto; margin-right: auto; margin-top: -25px; padding-top: 20px;

第18章—后端分页(Mybatis)

spring boot 系列学习记录:http://www.cnblogs.com/jinxiaohang/p/8111057.html 码云源码地址:https://gitee.com/jinxiaohang/springboot 本次练习在之前第04章-整合Mybatis基础上进行,也算是Bootstrap-Table基础上进行扩展. 在使用mybatis时,我会将实体类属性和表字段名一致,这样可以不用配映射关系,会自动映射. 在使用JPA时,要以一定方式进行设置实体类属性和表字段名,举个例

SQL前后端分页

/class Page<T> package com.neusoft.bean; import java.util.List; public class Page<T> { private List<T> data; //后台数据库查询出来 private int totalRecord; //表示总共有多少记录,从数据库中查询出来 // private int totalPage; // 表示总共有多少页,计算得到! // private int index; //表

Django后端分页及前端显示效果

1.导入分页相关模块 from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger 2.将对象分页,如下是按每页3条记录分页 customer_list = models.Customer.objects.all() paginator = Paginator(customer_list,3) 翻到第1页:paginator.page(1) 翻到最后一页:paginator.page(paginator.num_pa

第19章—后端分页(PageHelper)

spring boot 系列学习记录:http://www.cnblogs.com/jinxiaohang/p/8111057.html 码云源码地址:https://gitee.com/jinxiaohang/springboot PageHelper开源分页工具: https://gitee.com/free/Mybatis_PageHelper https://github.com/pagehelper/Mybatis-PageHelper 本次练习在之前第04章-整合Mybatis基础上

后端分页

一.分页的概念: 总页数:    totalPages                  总页数                               从后台 获取总记录数:   totalRecordsCount    总的信息的数量                 从后台获取每页容量: pageSize                    每页显示信息的数量          前台自定当前页: currentPage                   当前在哪个分页上面     

ABP之展现层(Datatables分页)

在前面的随笔中,已经介绍了ABP的增删改查的操作,但是对于查询的数据并没有进行分页,只是进行粗糙的展示,今天的随笔中将摸索进行分页展示.这里打算使用的分页插件是DataTables,这是一款比较强大的表格插件. 在以前我们后台手动分页的时候,需要前台传入两个重要的分页参数:PageIndex和PageSize(显示第几页的数据和每页显示的数量),这是必须的量的参数.分页作为一个页面展示的基础功能,ABP框架已经对分页功能进行了一些方便性的操作,为我们提供了一些有助于分页的接口和Dto,Dto是什

用DataTables实现服务器端分页

推荐下,H-ui.admin 模版里面使用了DataTables,而且把常用功能都给实现的很完整了,推荐去参考H-ui的模版源码参考! 分享几篇有价值的文章: DataTables 的官网:https://datatables.net Bootstrap插件DataTables实现服务器端分页http://lovelock.coding.me/javascript/bootstrap-plugin-datatables/ PHP+Ajax+Datatables实现分页https://blog.c

Django中使用JS通过DataTable实现表格前端分页,每页显示页数,搜索等功能

版本: django:2.1.7 python:3.7 Django架构中自带了后端分页的技术,通过Paginator进行分页,前端点击按钮提交后台进行页面切换. 优缺点:后端分页对于数据量大的场景有其优势,但页面切换比较慢. 后端分页python3代码如下: paginator = Paginator(stat_list, numtmp) try: flight_stats = paginator.page(1) except PageNotAnInteger: flight_stats =