Datatables插件是一款方便简单的展现数据的列表插件。关于基本使用,官方网站上的已介绍的很详细,这里我再稍微过一下。javascript
<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>
```css <link href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css" rel="stylesheet"> ```
```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> ```
```javascript <script type="text/javascript"> $(document).ready(function() { $('#example').DataTable(); } ); </script> ```
这里以一个展现用户姓名年龄的表格举例。假设数据库(数据库使用Django默认自带数据库)中有表格User,它的字段有name、age两项。css
基本使用的话,则是django做为后端,将要显示的数据传给DataTables进行展现。具体用法比较简单,DataTables的官网也很详细了。(官网文档都是第一份资料)
很少说,直接上代码html
def get_basic_tables(request): """ 建立基本的DataTables表格 """ user_list = [] for user_info in User.objects.all(): user_list.append({ 'name': user_info.name, 'age': user_info.age }) return render(request, 'example/basic_tables.html', { 'users': user_list })
上面代码主要就是将数据取出并返回。
前端的展现代码以下:前端
<table id="basic-table" class="table table-hover" width="100%"> <thead> <tr> <th>学号</th> <th>姓名</th> <th>年龄</th> </tr> </thead> <tbody> </tbody> </table>
$(document).ready(function () { $("#basic-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要展现的数据.users即为后台传递过来的数据 data: {{ users | safe }}, columns: [ { data: null, width: "1%", // 若想前端显示的不同,则须要"render"函数 'render': function (data, type, full, meta) { return meta.row + 1 + meta.settings._iDisplayStart; } }, { data: "name", 'render': function (data, type, full, meta) { return '<a class="text-warning" style="color:#007bff" title="年龄为'+ full.age +'">'+ data +'</a>'; } }, {data: 'age'} ] }) });
能够看到html中只初始化了表头,表的内容则在javascript中控制。最终显示出来的数据行,第一列是对表格数据的排序。从代码中看出,当data对应的数据被置为null时,单元格中的内容将由"render"对应的函数返回值决定。第一列datarender函数中meta.row至关于表格中行的索引,默认是从0开始,故为了学号显示从1开始,进行了加1操做。
render函数中的四个参数可谓是大有做用。 参数data恰好就是该函数上方“data”键对应的值的内容,好比第二列中的数据为‘data”键的值为name,则render函数中data就是name。而参数full至关于后端传递过来的users中的每一个user的索引,这样某一个单元格的内容想与它所在行的其余单元格进行互动,则可用full参数来传递。表格中当使用鼠标移动到名字上时,会显示到该人名的年龄,这一功能就是使用了full:java
{ data: "name", 'render': function (data, type, full, meta) { return '<a class="text-warning" style="color:#007bff" title="年龄为'+ full.age +'">'+ data +'</a>'; } },
这种使用方法,则是前端发送ajax请求去后端获取数据,而不是一开始就有后端将数据传送到前端的。当数据再由后端传递回前端时,前端会本身进行处理,如分页等。下面例子是展现年龄为22周岁的人员表格python
<table id="ajax-table" class="table table-hover" width="100%"> <thead> <tr> <th>学号</th> <th>姓名</th> <th>年龄</th> </tr> </thead> <tbody> </tbody> </table>
html页面中依旧只是初始化了表头。jquery
$(document).ready(function () { //django post请求须要加认证,不能忘了 $.ajaxSetup({ data: {csrfmiddlewaretoken: '{{ csrf_token }}' } }); var table = $('#ajax-table').DataTable({ "pagingType": "full_numbers", // 跟基本使用对比,已经没有data属性,而是多了"ajax" "ajax":{ "processing": true, // ajax请求的网址 "url": "{% url 'example:request_ajax' %}", "type": 'POST', "data": { // 前端向后端传递的数据age,好比只查询年龄在22岁的人员 "age": 22 }, // "dataSrc": "" }, // ajax请求成功传递回来后数据的展现 columns: [ { data: null, width: "1%", // 若想前端显示的不同,则须要"render"函数 'render': function (data, type, full, meta) { return meta.row + 1 + meta.settings._iDisplayStart; } }, { data: "name", 'render': function (data, type, full, meta) { return '<a class="text-warning" style="color:#007bff" title="年龄为'+ full.age +'">'+ data +'</a>'; } }, {data: 'age'} ], "language": { "processing": "正在获取数据,请稍后...", "lengthMenu": "选择每页 _MENU_ 展现 ", "zeroRecords": "未找到匹配结果--抱歉", "info": "当前显示第 _PAGE_ 页结果,共 _PAGES_ 页, 共 _TOTAL_ 条记录", "infoEmpty": "没有数据", "infoFiltered": "(获取 _MAX_ 项结果)", "sLoadingRecords": "载入中...", "paginate": { "first": "首页", "previous": "上一页", "next": "下一页", "last": "末页" } } } ); });
后端代码处理ajax请求:git
def request_ajax(request): """ 处理ajax的例子中的post请求 :param request: :return: """ try: if request.method == "POST": # print(request.POST) # 获取到前端页面ajax传递过来的age age = int(request.POST.get('age', 22)) user_list = [] for user_info in User.objects.filter(age=age): user_list.append({ 'name': user_info.name, 'age': user_info.age }) # 主要是将数据库查询到的数据转化为json形式返回给前端 return HttpResponse(json.dumps(user_list), content_type="application/json") else: return HttpResponse(f'非法请求方式') except Exception as e: return HttpResponse(e.args)
相比来看跟基本使用没多少区别,只是多了一步ajax请求而已。github
当咱们要往前端展现的数据量过大时,若是仍是一股脑将数据所有扔给前端来处理,那么你会发现前端分页加载的性能不好,这时咱们能够将分页操做放到后端来作。
其实将分页放到后端的意思就是对后台数据库中的数据进行部分请求。咱们首先能够这样想:“用户在前端页面查看表格时,他其实只关心这一页数据,他看不到其余页的数据。要看到其余页的数据,他必须得点击网页中的上一页或下一页按钮。” 理解了这一点,咱们是否能够这样作,即:“用户想看哪一页的数据,我就只去后台数据库查询这一页的数据。” 有了这样的理解,下来就是具体操做了。这个思路其实相似与Python语法中列表的切片功能,例如:ajax
test_list = [1, 3, 4, 5, 6, 7, 8, 9, 10, 11] # 测试咱们只须要这个列表中第3个到6个这4条数据,那么用列表的切片 little_list = test_list[2:6]
要查询到某一页展现的数据是哪些,必须知道这一页的数据的对应的数据起始位置和结束位置。
刚好在DataTables中,每次用户点击翻页(上一页或下一页)按钮时,前端都会向后端发送一次ajax请求。 而此次请求,前端则会将这一页的起始位置与结束位置传递到后端。
下面上代码:
<table id="basic-table" class="table table-hover" width="100%"> <thead> <tr> <th>学号</th> <th>姓名</th> <th>年龄</th> </tr> </thead> <tbody> </tbody> </table>
$(document).ready(function () { //django post请求须要加认证,不能忘了 $.ajaxSetup({ data: {csrfmiddlewaretoken: '{{ csrf_token }}' } }); var table = $('#backend-table').DataTable({ "pagingType": "full_numbers", // 跟基本使用对比,已经没有data属性,而是多了"ajax" searching: false, destroy: true, stateSave: true, // 此处为ajax向后端请求的网址 sAjaxSource: "{% url 'example:request_backend' %}", "processing": false, "serverSide": true, "bPaginate" : true, "bInfo" : true, //是否显示页脚信息,DataTables插件左下角显示记录数 "sDom": "t<'row-fluid'<'span6'i><'span6'p>>",//定义表格的显示方式 //服务器端,数据回调处理 "fnServerData" : function(sSource, aoData, fnCallback) { $.ajax({ "dataType" : 'json', // 此处用post,推荐用post形式,get也能够,但可能会遇到坑 "type" : "post", "url" : sSource, "data" : aoData, "success" : function(resp){ fnCallback(resp); } }); }, // ajax请求成功传递回来后数据的展现 columns: [ { data: null, width: "1%", // 若想前端显示的不同,则须要"render"函数 'render': function (data, type, full, meta) { return meta.row + 1 + meta.settings._iDisplayStart; } }, { data: "name", 'render': function (data, type, full, meta) { return '<a class="text-warning" style="color:#007bff" title="年龄为'+ full.age +'">'+ data +'</a>'; } }, {data: 'age'} ], "language": { "processing": "正在获取数据,请稍后...", "lengthMenu": "选择每页 _MENU_ 展现 ", "zeroRecords": "未找到匹配结果--抱歉", "info": "当前显示第 _PAGE_ 页结果,共 _PAGES_ 页, 共 _TOTAL_ 条记录", "infoEmpty": "没有数据", "infoFiltered": "(获取 _MAX_ 项结果)", "sLoadingRecords": "载入中...", "paginate": { "first": "首页", "previous": "上一页", "next": "下一页", "last": "末页" } } } ); // 每隔5秒刷新一次数据 // setInterval(refresh, 5000); }); function refresh() { var table = $('#backend-table').DataTable(); table.ajax.reload(null, false); // 刷新表格数据,分页信息不会重置 }
后端代码:
# 暂时跳过csrf的保护 @csrf_exempt def request_backend(request): """ 处理后端分页例子中的post请求 :param request: :return: """ try: if request.method == "POST": # 获取翻页后该页要展现多少条数据。默认为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 # 开始查询数据库,只请求这两个位置之间的数据 users = User.objects.all()[page_start:page_end] total_length = User.objects.all().count() user_list = [] for user_info in users: user_list.append({ 'name': user_info.name, 'age': user_info.age }) # print(start, ":", length, ":", draw) # 此时的key名字就是aaData,不能变 rest['aaData'] = user_list # 总记录数量 rest['iTotalDisplayRecords'] = total_length return HttpResponse(json.dumps(rest), content_type="application/json") else: return HttpResponse(f'非法请求方式') except Exception as e: return HttpResponse(e.args)
若是咱们想让前端实现定时刷新,能够用js的setInterval方法。具体以下:
function refresh() { var table = $('#backend-table').DataTable(); table.ajax.reload(null, false); // 刷新表格数据,分页信息不会重置 } // 每隔5秒刷新一次数据 setInterval(refresh, 5000);
以上的还有好多的dataTables插件的方法没有使用到,官网有不少的使用事例,也很是详细,此处也只是把经常使用到的进行了概括。这里多说一句,关于ajax请求后DataTables默认的查询会不起做用,但它会将查询框中的text经过ajax返回,须要本身在后端进行处理。 以上内容如有错误,请及时指正哈!