Django使用DataTables插件总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xiaobai_ol/article/details/82714892

Django使用Datatables插件总结

基本使用

Datatables插件是一款方便简单的展示数据的列表插件。关于基本使用,官方网站上的已介绍的很详细,这里我再稍微过一下。

  1. js配置。包含jquery和datatables的js
   <script src="https://code.jquery.com/jquery-3.3.1.js"></script>
    <script stc="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
  1. css配置。包含dataTables的css

     <link href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css" rel="stylesheet">
    
  2. html。初始化表格

     <table id="example" class="display" style="width:100%">
            <thead>
                <tr>
                    <th>Name</th>
                    <th>Position</th>
                    <th>Office</th>
                    <th>Age</th>
                    <th>Start date</th>
                    <th>Salary</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>Tiger Nixon</td>
                    <td>System Architect</td>
                    <td>Edinburgh</td>
                    <td>61</td>
                    <td>2011/04/25</td>
                    <td>$320,800</td>
                </tr>
                <tr>
                    <td>Garrett Winters</td>
                    <td>Accountant</td>
                    <td>Tokyo</td>
                    <td>63</td>
                    <td>2011/07/25</td>
                    <td>$170,750</td>
                </tr>
                <tr>
                    <td>Ashton Cox</td>
                    <td>Junior Technical Author</td>
                    <td>San Francisco</td>
                    <td>66</td>
                    <td>2009/01/12</td>
                    <td>$86,000</td>
                </tr>
            </tbody>
        </table>
    
  3. js配置。是表格dataTable化

     <script type="text/javascript">
         $(document).ready(function() {
            $('#example').DataTable();
        } );
     </script>
    

与django结合使用

基本使用

基本使用的话,则是django作为后端,将要显示的数据传给dataTables,dataTables负责展示。比较简单,关于用法,dataTables的官网也很详细了。(官网文档都是第一份资料)
不多说,直接上代码

def getData(request):
    try:
        modules_info = []
        module_list = sorted(set([build.module for build in Build.objects]))
        for module in module_list:
            total = Build.objects(module=module).count()
            success_count = Build.objects(module=module, ret_flag=1).count()
            data = {
                'module': module,
                'total': total,
                'success_count': success_count,
            }
            modules_info.append(data)
        return render(request, 'autotest/commitInfo.html', {
            'modules_info': json.dumps(modules_info),
            'dateChose': dateChose,
        })
    except Exception as e:
        return HttpResponse(e.args)

假如数据库表中有"module"、"ret_flag"等字段(这里我的数据库用的是mongoDB,其他数据库也都同理)。

id module ret_flag
aa module1 1
bb module1 1
cc module2 0

主要就是将数据取出,按照ret_flag字段统计求和等。然后转化为json或者字典的格式返回。
前端的展示代码如下:

<table id="module-table" class="table table-hover" width="100%">
    <thead>
        <tr>
            <th style="width: 1%">#</th>
            <th>名字</th>
            <th>总数</th>
            <th>成功次数</th>
        </tr>
    </thead>
    <tbody>
    </tbody>
</table>
//初始化数据表
$("#module-table").DataTable({
    // 表下方页脚的类型,具体类别比较到,见[官网](https://datatables.net/examples/basic_init/alt_pagination.html)
    "pagingType": "simple_numbers",
    //启动搜索框
    searching: true,
    destroy : true,
    // 保存刷新时原表的状态
    stateSave: true,
    // 将显示的语言初始化为中文
    "language": {
        "lengthMenu": "选择每页 _MENU_ 展示 ",
        "zeroRecords": "未找到匹配结果--抱歉",
        "info": "当前显示第 _PAGE_ 页结果,共 _PAGES_ 页",
        "infoEmpty": "没有数据",
        "infoFiltered": "(获取 _MAX_ 项结果)",
        "paginate": {
            "first": "首页",
            "previous": "上一页",
            "next": "下一页",
            "last": "末页"
        }
    },
    // 此处重要,该data就是dataTables要展示的数据,这里刚好是后端传递过来的数据。注意加django中引用模板语言,加safe。
    data: {{ modules_info | safe }},
    columns: [
          {
             data: null,
             width: "1%",
              // 若想前端显示的不一样,则需要"render"函数
              'render': function (data, type, full, meta) {
                     return meta.row + 1 + meta.settings._iDisplayStart;
                     }
           },
           {
               data: "module",
               'render': function (data, type, full, meta) {
                      return '<a class="text-warning" style="color:#007bff" href="{% url 'test:index'%}'+ data +'">'+ data +'</a>';
                      }
            },
            {data: 'total'},
            {data: 'success_count'}
             ]
    })

可以看到html中只初始化了表头,表的内容则是js中控制。最终显示出来的数据行,第一列是对表格数据的数字排序,从上面看出,data对应的数据被置为null,"render"对应的函数中meta.row相当于表格数据中对应数据的位置索引,默认是从0开始的,所以加了1。
对于"render"函数,其返回的字符串,则就会作为前端对应的表单元格的html显示效果。这里对于其函数中的四个参数可谓是大有作用。 参数data刚好就是上面data的值,比如第二列中的数据为‘data: “module”’则对应的render函数中的data就会指向它所指的module值。而参数full呢。则相当于后端往前端传递的该行的总数据对象。如果你想在某一列的初始化中引用另外列的值,则完全可以用full。比如最常见的给某列展示的数据加超链接:

           {
               data: "module",
               'render': function (data, type, full, meta) {
                      return '<a class="text-warning" style="color:#007bff" href="{% url 'test:index'%}'+ full.success_count +'">'+ data +'</a>';
                      }
            },

则对于前端的列表展示的是module的值,但其超链接则是用后端传递过来的数据中的success_count对应的值组成的。render对应函数的其他两个参数暂时没研究哈,O(∩_∩)O~

ajax请求数据使用

基本操作

这种使用方法,则是前端主动向后端发送ajax请求去获取数据,而不是一开始就有后端将数据传送到前端。此时的数据,前端会自动将数据表格分页(默认每行10条数据)。上代码

<table id="test-list" class="table table-hover table-striped projects" style="width: 100%;" role="grid">
    <thead>
        <tr>
            <th>测试条例</th>
            <th>测试名</th>
            <th>测试任务号</th>
            <th>测试时间</th>
            <th>测试状态</th>
        </tr>
    </thead>
    <tbody>
    </tbody>
</table>

html页面中依旧只是初始化了表头。

             //django post请求需要加认证,不能忘了
            $.ajaxSetup({
                data: {csrfmiddlewaretoken: '{{ csrf_token }}' }
            });
            var table = $('#test-list').DataTable({
                "pagingType": "full_numbers",
                "order": [[ groupColumn, 'asc' ]],
                // 跟上面的基本使用对比,已经没有data属性,而是多了"ajax"
                "ajax":{
                    "processing": true,
                    // ajax请求的网址
                    "url": "{% url 'test:Tests' %}",
                    "type": 'POST',
                    "data": {
                        // 前端向后端传递的数据buildId
                        "buildId": "id"
                    },
                    // 
                    "dataSrc": ""
                },
                // ajax请求成功传递回来后数据的展示
                columns: [
                    {
                        data: "test_a",
                        "visible": false
                    },
                    {
                        data: "project"
                    },
                    {
                        data: "test_url",
                        'render': function (data, type, full, meta) {
                            
                                return '<a target="_blank" style="color:#007bff" href="'+ data +'">'+ test_num +'</a>'

                    },
                    {
                        data: "test_time",
                    },
                    {
                        data: "status",
                    }
                ],
                "language": {
                    "processing": "正在获取数据,请稍后...",
                    "lengthMenu": "选择每页 _MENU_ 展示 ",
                    "zeroRecords": "未找到匹配结果--抱歉",
                    "info": "当前显示第 _PAGE_ 页结果,共 _PAGES_ 页, 共 _TOTAL_ 条记录",
                    "infoEmpty": "没有数据",
                    "infoFiltered": "(获取 _MAX_ 项结果)",
                    "sLoadingRecords": "载入中...",
                    "paginate": {
                        "first": "首页",
                        "previous": "上一页",
                        "next": "下一页",
                        "last": "末页"
                    }
                }
            } );

def Tests(request):
    try:
        if request.method == "POST":
            // 获取到前端ajax传递过来的buildId
            buildId = request.POST['buildId']
            # print(request.POST)
            # 数据库查询等操作
            build = Build.objects(id=buildId).first()
            test_list = Test.objects(cnt_build=build)
            tests_info = []
            # 按实际情况做,主要是将数据库查询到的数据转化为json形式返回给前端
            for test in test_list:
                # 注意字典中的key名字要和前端的对应一致
                data = {
                    "test_a": test.a,
                    "project": test.project,
                    "test_url": test.test_url,
                    "test_time": test.test_time,
                    "status": test.status,
                }
                tests_info.append(data)
            return HttpResponse(json.dumps(tests_info), content_type="application/json")
        else:
            return HttpResponse('非法请求方式')
    except Exception as e:
        return HttpResponse(e.args)

相比来看跟基本使用没多少区别,只是多了一步跟平时一样的ajax请求而已。

后端分页

有时候当我们要往前端展示的数据量过大的时候,如果还是一股脑将数据全部扔给前端,由前端来分页的话,那么在点击下一页或上一页的时候,会变得很卡很卡。所以呢,我们将前端的分页放到后端来做。
其实放到后端来做,并不是说要怎样,刚才也顺带提了,经过观察,当dataTables插件使用ajax时,**每次我们点击翻页(上一页或下一页)的时候,前端都会向后端发送一次ajax请求。***那么我们就完全可以利用这个特点。这样做:每次前端点击翻页的时候,它通过ajax请求后端后,后端只给它返回翻页后这一页的数据并供前端展示。也就是说,后端在查询数据库的时候,只查询一小段的数据(相当于python中列表的切片)。显然这样数据库查询的数据少了,前端也就不用累着去做分页了。多么美好的事情。
刚说了那么多,数据库若要只查询表中的一小段数据,那么我们必须得知道这一段数据,是从哪开始到哪里结束,就相当于python列表中, 例如:

test_list = [1, 3, 4, 5, 6, 7, 8, 9, 10, 11]
# 测试我们只需要这个列表中第3个到6个这4条数据,那么用列表的切片
little_list = test_list[2:6]

因此,我们必须知道前端展示这一页时,是从总数据表中的哪个地方开始,哪个地方结束的。很幸运,dataTables的ajax每次请求时,会将这两个数据自动传递过来。下面上代码:

<table class="table table-bordered table-striped table-hover" id="test-table" style="width: 100%">
    <thead>
        <tr>
            <th style="width: 1%">#</th>
            <th>第一列</th>
            <th>第二列</th>
            <th>第三列</th>
            <th style="width: 20%">第四列</th>
            <th>第五列</th>
        </tr>
    </thead>
    <tbody>

    </tbody>
</table>
             //django post请求需要加认证,不能忘了
            $.ajaxSetup({
                data: {csrfmiddlewaretoken: '{{ csrf_token }}' }
            });
            //初始化ajax的datatable
            $("#test-table").DataTable({
                "pagingType": "simple_numbers",
                searching: false,
                destroy: true,
                stateSave: true,
                // 此处为ajax向后端请求的网址
                sAjaxSource: "{% url 'test:getTest' %}",
                "processing": false,
                "serverSide": true,
                "bPaginate" : true,
                "bInfo" : true, //是否显示页脚信息,DataTables插件左下角显示记录数
                "sDom": "t<'row-fluid'<'span6'i><'span6'p>>",//定义表格的显示方式
                "sPaginationType": "bootstrap",
                //服务器端,数据回调处理
                "fnServerData" : function(sSource, aoData, fnCallback) {
                    $.ajax({
                        "dataType" : 'json',
                        // 此处用post,推荐用post形式,get也可以,但可能会遇到坑
                        "type" : "post",
                        "url" : sSource,
                        "data" : aoData,
                        "success" : function(resp){
                            fnCallback(resp);
                        }
                    });
                },

                columns: [
                    {
                        data: null,
                        width: "1%",
                        'render': function (data, type, full, meta) {
                            return meta.row + 1 + meta.settings._iDisplayStart;
                        }
                    },
                    {
                        width: "10%",
                        data: "test1",
                    },
                    {
                        data: "module",
                    },
                    {
                        data: "name",
                    },
                    {
                        data: null,
                        'render': function (data, type, full, meta) {
                            var content = '<div class="progress progress-striped  progress_sm" style="margin-bottom:0px">';
                            return content
                        }
                    }

                ],
                "language": {
                    "processing": "正在获取数据,请稍后...",
                    "lengthMenu": "选择每页 _MENU_ 展示 ",
                    "zeroRecords": "未找到匹配结果--抱歉",
                    "info": "当前显示第 _PAGE_ 页结果,共 _PAGES_ 页, 共 _TOTAL_ 条记录",
                    "infoEmpty": "没有数据",
                    "infoFiltered": "(获取 _MAX_ 项结果)",
                    "sLoadingRecords": "载入中...",
                    "paginate": {
                        "first": "首页",
                        "previous": "上一页",
                        "next": "下一页",
                        "last": "末页"
                    }
                }
            });
def getTest(request):
    if request.method == 'GET':
        return render(request, 'test/index.html', )
    else:
        # 获取翻页后该页要展示多少条数据。默认为10;此时要是不清楚dataTables的ajax的post返回值
        # 可以打印一下看看【print(request.POST)】
        page_length = int(request.POST.get('iDisplayLength', '10'))
        # 该字典将转化为json格式的数据返回给前端,字典中的key默认的名字不能变
        rest = {
            "iTotalRecords": page_length,  # 本次加载记录数量
        }
        # 获取传递过来的该页的起始位置,第一页的起始位置为0.
        page_start = int(request.POST.get('iDisplayStart', '0'))
        # 该页的结束位置则就是"开始的值 + 该页的长度"
        page_end = page_start + page_length
        # 开始查询数据库,只请求这两个位置之间的数据
       
        builds = Build.objects[page_start: page_end]
        
        build_data = []
        for build in builds:
            data = {
                "tes1": build.test,
                "module": build.module,
                "name": build.name,
            }
            build_data.append(data)
        # print(start, ":", length, ":", draw)
        # 此时的key名字就是aaData,不能变
        rest['aaData'] = build_data
        # 总记录数量
        rest['iTotalDisplayRecords'] = total_length
        return HttpResponse(json.dumps(rest), content_type="application/json")

此时,如果我们想让前端实现定时刷新,可以用js的setInterval方法。具体如下:

function refresh() {
        var table = $('#test-table').DataTable();
        table.ajax.reload(null, false); // 刷新表格数据,分页信息不会重置
}
// 每隔5秒刷新一次数据
setInterval(refresh, 5000);

最后

关于上面的举例,比如给网页配置路由,在url.py中配置网址等给省略掉了,相信这个也很简单哈!
以上的还有好多的dataTables插件的方法没有使用到,官网有很多的使用事例,也非常详细,此处也只是把自己常用到的归纳了一下。作为一个搬运工,也只是从别处搬一搬。这里多说一句,关于ajax请求后dataTable默认的查询会不起作用,但它会将查询处的text通过ajax返回,需要自己将要查询的内容在后端处理,并将结果返回到前端展示。

猜你喜欢

转载自blog.csdn.net/xiaobai_ol/article/details/82714892