Django使用DataTables插件總結

Django使用Datatables插件總結

文章中的例子已上傳至github

基本使用

Datatables插件是一款方便簡單的展現數據的列表插件。關於基本使用,官方網站上的已介紹的很詳細,這裏我再稍微過一下。javascript

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兩項。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請求數據使用

基本操做

這種使用方法,則是前端發送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返回,須要本身在後端進行處理。 以上內容如有錯誤,請及時指正哈!

相關文章
相關標籤/搜索