使用 django 处理大型 jquery 数据表很慢

Posted

技术标签:

【中文标题】使用 django 处理大型 jquery 数据表很慢【英文标题】:large jquery datatables are slow with django 【发布时间】:2020-01-03 04:13:05 【问题描述】:

我正在通过 django 显示一个 20k 行的 jquery 数据表。渲染非常慢。所以我想知道有什么替代方法可以更快地处理它,例如,通过延迟渲染,只加载显示的部分?数据库在sql中。

我尝试在数据表选项中将 deferRender 和 serverSide 选项设置为 true,但它仍然很慢。我了解这些选项仅在通过 AJAX 调用数据时才有效。数据表网站中给出的示例只是将 AJAX 数据转储到预定义列中。就我而言,我使用数据作为参数来生成链接和创建图标等。

代码如下:

<div class="container col-9 pb-5 mb-5">
    <table id="drugstable" class="table table-hover" style="width: 100%">
            <thead>
              <tr>
                <th scope="col">#</th>
                <th scope="col">Drug</th>
                <th scope="col">Tool</th>
                <th scope="col">netZoo release</th>
                <th scope="col">Network</th>
              </tr>
            </thead>
            <tbody>
             % for drug in drugs %
                <tr>
                <th scope="row"> forloop.counter </th>
                <td><a href=" drug.drugLink "> drug.drug </a></td>
                <td> drug.tool </td>
                <td> drug.netzoo  <a href=" drug.netzooLink "> drug.netzooRel </a></td>
                <td><a href=" drug.network " download><i class="fas fa-download"></i></a></td>
                </tr>
             % endfor %

            </tbody>
          </table>

这里是对应的javascript

<script>
$(function () 
  $('[data-toggle="popover"]').popover();
)

// Basic example
$(document).ready(function() 
    //datatables
    $('#drugstable').DataTable(
      "dom": "<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'f>>" +
             "<'row'<'col-sm-12'tr>>" +
             "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
    );
 );
</script>

【问题讨论】:

用谷歌搜索网格控件。有很多可供选择。我自己使用 w2ui.com。 IT 有很多选择。 20k 条记录将花费大量时间,即使您只是将它们放在预呈现的 html 文件中。 【参考方案1】:

如 cmets 中所述,20,000 行将花费浏览器使用 jQuery DataTables 呈现的大量时间。您可能想研究使用带有分页加载的 jQuery DataTables。为此,您需要使用 Django REST Framework 之类的工具从 Django 后端提供数据。

在 jQuery 中正确配置是很棘手的。假设您有一个 Django REST Framework 端点,它从您的 Django 模型中提供了三个字段,分别称为 col1col2col3。这是从名为https://example.com/api/my-endpoint/ 的端点逐步加载它的 JavaScript 和 HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <!-- Include jQuery and DataTables -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.css">
    <script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.js"></script>

    <title>My API in Data Tables</title>
</head>
<body>
    <table class="table table-hover"  id="mydatatable">
        <thead>
            <tr>
                <th>col1</th>
                <th>col2</th>
                <th>col3</th>
            </tr>
        </thead>
        <tbody>
        </tbody>
    </table>
<script>
    url = "https://example.com";
    endpoint = "/api/my-endpoint/";

    table = $('#mydatatable').DataTable(
        "processing": true,
        "serverSide": true,
        "lengthMenu": [10, 25, 50, 100],
        "pagingType": "simple",
        "info": true,
        "ajax": 
            "url": url + endpoint,
            "beforeSend": function (request) 
                request.setRequestHeader("Authorization", "Token MyTokenMyTokenMyTokenMyToken");
            ,
            "data": function(d) 
                // Map DataTables field names to DRF field names
                // DataTables `start` becomes DRF `offset`
                // DataTables `length` becomes DRF `limit`
                //
                // Routines handle converting DataTables ordering and search
                // values for the DRF on input

                d.offset = d.start;
                d.limit = d.length;

                var ordering = '';
                $.each(d.order, function(k, v) 
                    if (v.dir == 'desc') 
                        ordering = '-';
                    
                    if (d.columns[v.column].data == 'client_obj')  // catch ordering on client_obj column
                        d.columns[v.column].data = 'client__name'; // convert it to 'client__name' field expected by DFR endpoint
                    
                    ordering += d.columns[v.column].data

                );
                d.ordering = ordering;
                d.search = d.search.value;
            ,
            "dataFilter": function(data) 
                // Map DRF field names to Data Tables field names
                // DRF `count` becomes DataTables `recordsTotal`
                // DRF `count` becomes DataTables `recordsFiltered`
                // DRF `results` becomes DataTables `data`

                var json = jQuery.parseJSON(data);
                json.recordsTotal = json.count;
                json.recordsFiltered = json.count;
                json.data = json.results;

                return JSON.stringify(json); // return JSON string
            ,
        ,
        columns: [
            data: 'col1',
            data: 'col2',
            data: 'col3'
        ]
    );
</script>
</body>
</html>

此示例还包括如何使用 DRF 包含的 Token Auth 发送用于 Token Authentication 的令牌,但如果您不需要身份验证,则不需要它。我希望这可以帮助您走上正轨。祝你好运!

【讨论】:

谢谢。这让我走上了寻找答案的道路。我最终使用了第三方插件github.com/izimobil/django-rest-framework-datatables。【参考方案2】:

jquery Datatable 具有分页选项,其中记录数由服务器端逻辑控制。

您可以通过添加"serverSide": true 类似这样的内容来激活分页

$('#example').DataTable(
    "processing": true,
    "serverSide": true,
    "ajax": "../server_side/scripts/server_processing.php"
);

Datatable 会动态添加一些参数到 API 调用中,这些参数可以用来在服务器端编写逻辑。

例如:

order:  asc
start:  20
length: 10

请参阅this post 了解更多详细信息和带有示例代码的现场演示

【讨论】:

以上是关于使用 django 处理大型 jquery 数据表很慢的主要内容,如果未能解决你的问题,请参考以下文章

跨 django 数据库移动大型数据集

加快 Django 表单以将大型(500k obs)CSV 文件上传到 MySQL 数据库

Django/jQuery:处理模板继承和 JS 文件加载

充满事件处理程序的巨大文件!如何在 AJAX Web 应用程序中组织大型 jQuery 文件?

使用大型列表优化 Django 查询集调用?

大型数据集的自动完成优化