Django使用Datatables插件总结

文章中的例子已上传至github

基本使用

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>

2. css配置。包含dataTables的css

```css
<link href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css" rel="stylesheet">
```

3. html。初始化表格

```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>
```

4. js配置。是表格dataTable化

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

与django结合使用

这里以一个展示用户姓名年龄的表格举例。假设数据库(数据库使用Django默认自带数据库)中有表格User,它的字段有name、age两项。

基本使用

基本使用的话,则是django作为后端,将要显示的数据传给DataTables进行展示。具体用法比较简单,DataTables的官网也很详细了。(官网文档都是第一份资料)

不多说,直接上代码

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:

   {
data: "name",
'render': function (data, type, full, meta) {
return '<a class="text-warning" style="color:#007bff" title="年龄为'+ full.age +'">'+ data +'</a>';
}
},

ajax请求数据使用

基本操作

这种使用方法,则是前端发送ajax请求去后端获取数据,而不是一开始就有后端将数据传送到前端的。当数据再由后端传递回前端时,前端会自己进行处理,如分页等。下面例子是展示年龄为22周岁的人员表格

<table id="ajax-table" class="table table-hover" width="100%">
<thead>
<tr>
<th>学号</th>
<th>姓名</th>
<th>年龄</th>
</tr>
</thead>
<tbody>
</tbody>
</table>

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

    $(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请求:

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请求而已。

后端分页

当我们要往前端展示的数据量过大时,如果还是一股脑将数据全部扔给前端来处理,那么你会发现前端分页加载的性能很差,这时我们可以将分页操作放到后端来做。

其实将分页放到后端的意思就是对后台数据库中的数据进行部分请求。我们首先可以这样想:“用户在前端页面查看表格时,他其实只关心这一页数据,他看不到其他页的数据。要看到其他页的数据,他必须得点击网页中的上一页或下一页按钮。” 理解了这一点,我们是否可以这样做,即:“用户想看哪一页的数据,我就只去后台数据库查询这一页的数据。” 有了这样的理解,下来就是具体操作了。这个思路其实类似与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 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返回,需要自己在后端进行处理。

以上内容若有错误,请及时指正哈!

Django使用DataTables插件总结的更多相关文章

  1. [jQuery]jQuery DataTables插件自定义Ajax分页实现

    前言 昨天在博客园的博问上帮一位园友解决了一个问题,我觉得有必要记录一下,万一有人也遇上了呢. 问题描述 园友是做前端的,产品经理要求他使用jQuery DataTables插件显示一个列表,要实现分 ...

  2. jquery.dataTables插件使用例子详解

    DataTables是一个jQuery的表格插件.这是一个高度灵活的工具,依据的基础逐步增强,这将增加先进的互动控制,支持任何HTML表格 效果图 代码 <!doctype html> & ...

  3. dataTables 插件学习整理

    在项目中使用了dataTables 插件,学习整理一下. dataTables 的官方中文网站 http://www.datatables.club 引入文件: 所有的都要引入 jq文件 1. dat ...

  4. Datatables插件1.10.15版本服务器处理模式ajax获取分页数据实例解析

    一.问题描述 前端需要使用表格来展示数据,找了一些插件,最后确定使用dataTables组件来做. 后端的分页接口已经写好了,不能修改.接口需要传入页码(pageNumber)和页面显示数据条数(pa ...

  5. django form 组件插件

    创建类: class RegForms(forms.Form): account = fields.CharField( required = True, #必填字段 max_length=12, m ...

  6. 前端Datatables自定义事件(监听Datatables插件一些常见的事件动作)

    今天开发项目的时候,用Datatables插件做前端分页列表,想在列表发生翻页.排序.搜索.改变单页显示数据条数这些行为的时候做一些其他的操作,看了半天Datatables官网终于找到可以监测到这些事 ...

  7. jQuery DataTables插件分页允许输入页码跳转

    背景说明 项目中使用jQuery DataTables插件来实现分页表格,但是默认的分页样式不能输入页码进行跳转,在页数非常多的时候使用很不方便,最主要的还是没有达到产品部门的设计要求,所以我需要寻找 ...

  8. django admin后台插件:django-suit入门

    去年9月底开始用django来做公司内部项目,开始对django有了一些了解,感觉django真的蛮强大的(也有很多人推荐flask,将来有空的话我会试试).今天的话只是介绍一个小东西,django管 ...

  9. 黑马在线教育项目---15-16、datatables插件

    黑马在线教育项目---15-16.datatables插件 一.总结 一句话总结: datatables插件也比较好用,引入好插件的js和css后,核心代码也就是插件的初始化,如果要修改配置可以百度 ...

随机推荐

  1. 数据库学习之二--SQL语句以及数据类型

    一.SQL语句种类: 1. DDL(Data Definition Language,数据定义语言)用来创建或者删除存储数据用的数据库以及数据库中的表;包含以下几种指令: a. CREATE:CREA ...

  2. [USACO17JAN] 晋升者计数 dfs序+树状数组

    [USACO17JAN] 晋升者计数 dfs序+树状数组 题面 洛谷P3605 题意:一棵有点权的树,找出树中所有\((u,v)\)的对数,其中\(u,v\)满足\(val(u)\le val(v)\ ...

  3. HDU3076 ssworld VS DDD

    嘟嘟嘟 友情提示:数据把\(hp1\)和\(hp2\)弄反了! 进入正题. 这题还是比较好想,令\(dp[i][j]\)表示第一个人赢了\(i\)场,第二个人赢了\(j\)的概率,转移就是分别考虑这一 ...

  4. 【概率论】3-6:条件分布(Conditional Distributions Part II)

    title: [概率论]3-6:条件分布(Conditional Distributions Part II) categories: Mathematic Probability keywords: ...

  5. linux下文件传输一些方法整理.

    ftp类 ftp 命令已经不推荐使用了. #基本用法 lftp sftp://[domain name] lftp sftp://theURL.org #使用不同用户名 lftp sftp://[us ...

  6. scrapy框架之Pipeline管道类

    Item Pipeline简介 Item管道的主要责任是负责处理有蜘蛛从网页中抽取的Item,他的主要任务是清洗.验证和存储数据.当页面被蜘蛛解析后,将被发送到Item管道,并经过几个特定的次序处理数 ...

  7. Ubuntu 14.04 网卡网关配置修改

    #添加网关route add default gw 192.168.5.1#强制修改网卡地址ifconfig eth0 192.168.5.40 netmask 255.255.255.0. 服务器需 ...

  8. Selenium处理页面懒加载方法

    在做selenium webdriver  在做UI自动化时,有些页面时使用懒加载的形式显示页面图片,如果在不向下移动滚动条时,获取到的图片会是网站的默认图片和真实的图片不相符. 1.滑动滚动条 1. ...

  9. [题解] [SDOI2015] 序列统计

    题面 题解 设 \(f[i][j]\) 代表长度为 \(i\) 的序列, 乘积模 \(m\) 为 \(j\) 的序列有多少个 转移方程如下 \[ f[i + j][C] = \sum_{A*B\equ ...

  10. 重读APUE(9)-SIG_ERR、SIG_DFL、SIG_IGN定义无参数

    下面这几个函数定义,每次看到都会纠结一阵子,奇怪的是为什么没有参数? #define SIG_ERR (void (*)())-1 #define SIG_DFL (void (*)())0 #def ...