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

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