首页 > 解决方案 > 当我加载超过 50000 行时,我在 django 中使用 js 的数据表非常慢

问题描述

我的模型:

class PartyMaster(models.Model):
    party_name = models.CharField(max_length=200,null=True, blank=True)
    email = models.EmailField(null=True, blank=True)
    contact = models.CharField(max_length=100,null=True, blank=True)
    address = models.CharField(max_length=350,null=True, blank=True)
    country = models.CharField(max_length=30,null=True, blank=True)
    sub_country = models.ForeignKey(CountryCategory,max_length=200,on_delete=models.CASCADE,null=True,blank=True,related_name='party_sub_country')
    state = models.CharField(max_length=50,null=True, blank=True)
    city = models.CharField(max_length=50,null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.party_name + " "+ self.email

我的观点:在我的模型中有 50 000+ 行

def party_list(request):
    parties = PartyMaster.objects.all()
    context = {
        'parties':parties,
    }
    return render(request,'party_master/party_edit.html',context)

我的模板:

{% extends 'base.html' %}
{% block title %} Party List's {% endblock %}

{% block body %}

<div class="container">
    <a href="{% url 'add_party' %}" class="btn btn-primary button_class mt-5">Party Master Form</a>
<div class="py-3">
    <div class="table-responsive">
    <table class="table table-striped  table-hover text-center table-responsive-sm" id="party_table">
        <thead class="table-head">
            <tr>

                <th scope="col">Party Name</th>
                <th scope="col">Email</th>
                <th scope="col">Contact</th>
                <th scope="col">Country</th>
                <th scope="col">Sub Country</th>
            </tr>
        </thead>
        <tbody>
            {% for party in parties %}
            <tr>

                <td class="pt-3">{{party.party_name}}</td>
                <td class="pt-3">{{party.email}}</td>
                <td class="pt-3">{{party.contact}}</td>
                <td class="pt-3">{{party.country}}</td>
                <td class="pt-3">{{party.sub_country.country_category}}</td>
            </tr>
            {% endfor %}

        </tbody>
    </table>

</div>
</div>
</div>

{% endblock %}

{% block js %}

    <!-- Datatable -->

    <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.25/css/jquery.dataTables.css">
    <script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.25/js/jquery.dataTables.js"></script>
    <script src="https://code.jquery.com/jquery-3.5.1.js"></script>
    <script src="https://cdn.datatables.net/1.10.25/js/jquery.dataTables.min.js"></script>
    <script src="https://cdn.datatables.net/buttons/1.7.1/js/dataTables.buttons.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/pdfmake.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/vfs_fonts.js"></script>
    <script src="https://cdn.datatables.net/buttons/1.7.1/js/buttons.html5.min.js"></script>
    <script src="https://cdn.datatables.net/buttons/1.7.1/js/buttons.print.min.js"></script>



<script>

    $(document).ready(function() {
        $('#party_table').DataTable( {
            dom: 'Bfrtip',
            "pageLength": 50,
            buttons: [
                {
                    extend: 'excelHtml5',
                    exportOptions: {
                        columns: [ 0, 1, 2, 3, 4 ]
                    }
                },
                {
                    extend: 'pdfHtml5',
                    exportOptions: {
                        columns: [ 0, 1, 2, 3, 4 ]
                    }
                },
            ]
        } );
    } );
</script>


{% endblock %}

如何通过服务器端处理加载数据?我很困惑如何在文档中使用帮助来实现。请从头开始提供完整的实现。

有什么替代方案也可以建议吗?

标签: jquerypython-3.xdjangodatatablesdjango-3.1

解决方案


使用 Datatables 处理大型数据集时,您希望避免在 TR 级别使用迭代,而是希望在 DataTable 定义中设置数据属性。

https://mail.datatables.net/forums/discussion/32107/how-to-load-an-array-of-json-objects-to-datatables

您可以通过在脚本标签中创建 JSON 对象然后迭代各方并构建 JSON 来做到这一点。

以这种方式定义数据源时,Datatables 呈现速度更快。

另一种方法是使用服务器端 AJAX ( https://datatables.net/examples/data_sources/ajax ) 您会找到的大多数示例都将使用 PHP。

对于您的代码,它将是这样的:

<script>
let data = [
{% for party in parties %}
    {
      "party_name": "{{ party.party_name }}",
      "email": "{{ party.email }}",
      "contact": "{{ party.contact }}",
      "country": "{{ party.country }}",
      "country_category": "{{ party.sub_country.country_category }}"
    }{% if not forloop.last %},{% endif %}
{% endfor %}
];

    $(document).ready(function() {
        $('#party_table').DataTable( {
            dom: 'Bfrtip',
            "pageLength": 50,
            buttons: [
                {
                    extend: 'excelHtml5',
                    exportOptions: {
                        columns: [ 0, 1, 2, 3, 4 ]
                    }
                },
                {
                    extend: 'pdfHtml5',
                    exportOptions: {
                        columns: [ 0, 1, 2, 3, 4 ]
                    }
                },
            ],
            data: data,
            columns: [
                { data: 'party_name'},
                { data: 'email'},
                { data: 'contact'},
                { data: 'country'},
                { data: 'country_category'}
            ]
        } );
    } );
</script>

因此,在第一部分中,您定义 JSON 结构,然后根据 data 参数将其传递到数据表配置中,然后使用 columns 参数告诉它使用数据的顺序

为了帮助调试和查看从您的数据库中提取了哪些记录,请改用它,这将显示源中记录的 PK,以便您可以交叉检查数据库

<script>
let data = [
{% for party in parties %}
    {
      /* PK={{ party.pk }} */
      "party_name": "{{ party.party_name }}",
      "email": "{{ party.email }}",
      "contact": "{{ party.contact }}",
      "country": "{{ party.country }}",
      "country_category": "{{ party.sub_country.country_category }}"
    }{% if not forloop.last %},{% endif %}
{% endfor %}
];

    $(document).ready(function() {
        $('#party_table').DataTable( {
            dom: 'Bfrtip',
            "pageLength": 50,
            buttons: [
                {
                    extend: 'excelHtml5',
                    exportOptions: {
                        columns: [ 0, 1, 2, 3, 4 ]
                    }
                },
                {
                    extend: 'pdfHtml5',
                    exportOptions: {
                        columns: [ 0, 1, 2, 3, 4 ]
                    }
                },
            ],
            data: data,
            columns: [
                { data: 'party_name'},
                { data: 'email'},
                { data: 'contact'},
                { data: 'country'},
                { data: 'country_category'}
            ]
        } );
    } );
</script>

推荐阅读