django 中嵌入datatable

需求:在頁面進行一個表格的渲染 並對錶格中的一些屬性進行排序

解決方法:由於表格內的數據過於龐大 一次渲染肯定要很長很長的時間 而且排序放在前端進行排序也需要很長很長的時間 我們把排序放在後臺 並且減少渲染的數據量,僅渲染頁面上的字值

具體的操作步驟:

1、在view 層寫好datatable 的後臺 這裏需要注意的是:

這個後臺是經過重載的:

代碼中的 all_data 爲在圖表中顯示的數據源(數據源經過處理以後爲普通list) 即發送到前端的數據源 前端的js也會實時的和後臺進行交互 實現數據排序 數據換頁等一系列操作

其中的 propeties 是和後臺的 js 代碼中cloums (列變量)一一進行對應的 在這個需求中主要執行後臺排序的工作 :(工作的步驟:前端點擊排序功能並(監聽下按照何種屬性何種順序 ) 傳輸給後臺 後臺相應到前端 然後根據 order_name = propeties[order_column] 調用all_data = sorted(chain(drugs),key= attrgetter(order_name), reverse = False) 進行排序)

由於是異步渲染 所以肯定不會將要渲染的數據一次性發送到前端的 ,根據all_data[start:start+length] 來進行切片操作(即選擇將要渲染的對象)

將要渲染的 對象發送到前端

class UsersList110Json(BaseDatatableView):
    total_records = -1
    total_display_records = -1
    
    def get_initial_queryset(self):
        print(self.request.GET)
        propeties = {#這個地方寫上表格的列序號和真實擡頭之間的對應關係,下面好order_by使用名稱
            # '0': 'smiles',
            # 將不在需要smiles 進行顯示
            '1': 'de_id',
            '2': 'logp',
            '3': 'mw',
            '4': 'h_a',
            '5': 'h_d',
        }
        
        draw = self.request.GET.get('draw')

        # 將要排序的列序號
        order_column = self.request.GET.get('order[0][column]')
        # 將要排序的方式  即按正序還是逆序
        order_dir = self.request.GET.get('order[0][dir]')

        start = int(self.request.GET.get('start'))
        length = int(self.request.GET.get('length'))

        
        de_id = self.request.GET.get('de_id')
        # print('我得到的deid'+ de_id)
        print('Ajax get de_id is ------------------->{}'.format(de_id))

        # 獲得 list 對象
        # drugs = models.LevelTwo.objects.filter(parent_id = de_id)
        
        drugs = models.ChildrenAndGrands.get_children_and_grands(de_id = de_id)
        
        order_name = propeties[order_column]
        print('order by --------------->{}'.format(order_name))
        # 默認用 升序
        all_data = sorted(chain(drugs),key= attrgetter(order_name), reverse = False)


        if order_dir == 'desc':
            all_data =  sorted(chain(drugs),key= attrgetter(order_name), reverse=True)
        
        self.total_records = self.total_display_records = len(all_data)
        # 生成將要顯示的圖片
        # 調用靜態方法
        
        starts = datetime.now()
        was_svg = all_data[start:start+length]
        make_ajax_svg(was_svg)
        ends = datetime.now() 
        print('processing svg------lasts: ', (ends - starts).seconds)        
        
        # print('all_data [10]------------------->{}'.format(all_data[10]))
        return all_data[start:start+length]
        # return all_data
    

    def filter_queryset(self, qs):
        return qs
    
    def get_context_data(self, *args, **kwargs):
        try:
            self.initialize(*args, **kwargs)

            # prepare columns data (for DataTables 1.10+)
            self.columns_data = self.extract_datatables_column_data()

            # determine the response type based on the 'data' field passed from JavaScript
            # https://datatables.net/reference/option/columns.data
            # col['data'] can be an integer (return list) or string (return dictionary)
            # we only check for the first column definition here as there is no way to return list and dictionary
            # at once
            self.is_data_list = True
            if self.columns_data:
                self.is_data_list = False
                try:
                    int(self.columns_data[0]['data'])
                    self.is_data_list = True
                except ValueError:
                    pass

            # prepare list of columns to be returned
            self._columns = self.get_columns()

            # prepare initial queryset
            qs = self.get_initial_queryset()

            # prepare output data
            if self.pre_camel_case_notation:
                aaData = self.prepare_results(qs)

                ret = {'sEcho': int(self._querydict.get('sEcho', 0)),
                       'iTotalRecords': self.total_records,
                       'iTotalDisplayRecords': self.total_display_records,
                       'aaData': aaData
                       }
            else:
                data = self.prepare_results(qs)

                ret = {'draw': int(self._querydict.get('draw', 0)),
                       'recordsTotal': self.total_records,
                       'recordsFiltered': self.total_display_records,
                       'data': data
                       }
            return ret
        except Exception as e:
            return self.handle_exception(e)  

前端的js代碼如下:

js 代碼用jquery 寫成,也是經過重載的 裏面的order 保證是使用什麼排序 2 表示用 第三列進行排序 asc 表示降序

中間的二維數組 中的第一個數組表示 長度的值 第二個中的數據用來顯示再前端 的選擇框中 如果第二個 數組中的數據變成[’'十個,‘三十個’,‘五十個’] ,前端的對應位置就會顯示爲十個 三十個 五十個

colums 表示列變量 表示再在datatable (表格中的顯示列)

其中有幾個屬性:

orderable 表示能否被排序

searchable 能否被 搜索

visible 是否被顯示在頁面中(默認爲顯示)

最後ajax 部分中的

url 是向後端發送的url 地址(在第二步中會提及 在第三步中會進行 定義)

data 爲向後端發送的數據

// 顯示在 tbody 中的內容
$(document).ready(function() {
    var dt_table = $('.datatable').dataTable({
        language: dt_language,  // global variable defined in html
        // 降序還是升序
        order: [[ 2, "asc" ]],
        // 二維數組,第一個數組用來作爲長度的值,第二個數組用來作爲顯示的選項。
        lengthMenu: [[10, 30, 50],['10', '30', '50']],
        // 列 變量
        columns: [
            {
                data: 'imgscr',
                "width": "400px",
                 render: function (data, type, row, meta) {                                           
                     return "<img style = 'width:300px;height:200px;transition:all 1s;' src='" + data + "' />";
                      //還可以給圖片加上超鏈接
                     //return "<a href='" + data + "'>" + data + "</a>";
                },
                orderable: false,
                searchable: true,
                className: "center"
            },

            {
                data: 'de_id',
                orderable: true,
                searchable: true,
                className: "center",
                visible : false,
            },
            {
                data: 'logp',
                orderable: true,
                searchable: true,
                className: "center"
            },
            {
                data: 'mw',
                orderable: true,
                searchable: true,
                className: "center"
            },
            {
                data: 'h_a',
                orderable: true,
                searchable: true,
                className: "center"
            },
            {
                data: 'h_d',
                orderable: true,
                searchable: true,
                className: "center"
            }


        ],

        searching: false,
        processing: true,
        serverSide: true,
        stateSave: false,

        ajax: {
            "url": USERS_LIST_JSON_URL,
            "data": function(d){
                return $.extend( {}, d, {
                    de_id : document.getElementById('de_id').innerText
                });
            }
        }
    });
});

2、添加前端的 html代碼 用來將list 渲染在前端 這裏我只截取了部分代碼 具體的代碼會在後面貼出

需要注意的是 js 的加載順序 jQuery frist then bootstrap 最後是額外的js

下面又一條 var USERS_LIST_JSON_URL = ‘{% url “users_list_json_110” %}’;在上面步驟的ajax 中會進行提到 在下一步中會進行定義

這個指向的是在後臺實現的 view 的url 將會在下一步進行創建 最終指向的是 上一步 view

<script src="{% static 'js/jquery-3.3.1.js' %}"></script>
<script src="{% static 'js/bootstrap.js' %}"></script>
<script src="{% static "loading/ddv_example_1_10.js" %}"></script>
<script type="text/javascript">
    var USERS_LIST_JSON_URL = '{% url "users_list_json_110" %}';
    // translations for datatables
    var dt_language = {
      "emptyTable": "{% trans "No data available in table" %}",
      "info": "{% trans "Showing _START_ to _END_ of _TOTAL_ entries" %}",
      "infoEmpty": "{% trans "Showing 0 to 0 of 0 entries" %}",
      "infoFiltered": "{% trans "(filtered from _MAX_ total entries)" %}",
      "infoPostFix": "",
      "thousands": ",",
      "lengthMenu": "{% trans "Show _MENU_ entries" %}",
      "loadingRecords": "{% trans "Loading..." %}",
      "processing": "{% trans "Processing..." %}",
      "search": "{% trans "Search: " %}",
      "zeroRecords": "{% trans "No matching records found" %}",
      "paginate": {
        "first": "{% trans "First" %}",
        "last": "{% trans "Last" %}",
        "next": "{% trans "Next" %}",
        "previous": "{% trans "Previous" %}"
            },
      "aria": {
        "sortAscending": "{% trans ": activate to sort column ascending" %}",
        "sortDescending": "{% trans ": activate to sort column descending" %}"
            }
    }
</script>

3、添加一條url 用來指向 datableview

url(r'^users_data_110/$', UsersList110Json.as_view(), name="users_list_json_110")

4、值得一提的是 這個頁面在渲染時是分開渲染的

用到了一個url 兩個view 最後又渲染到了同一個template

主線爲url -->普通view -->template

分線爲datatable view----> template

分線的執行過程爲 前端提交ajax 請求 匹配相應 的url url 找到 view 進行後臺操作

分線主要執行的任務 :根據前端的請求週而復始的請求後臺操做

5、最後的附件會加上datatable 的一般使用方法

源碼在:https://github.com/ggkong/django-datatable–demo

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章