You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

大数据集下DataTables渲染过慢,求AJAX+deferRender实现指导

嘿,我来帮你搞定这个DataTables加载慢的问题!3000+条记录一次性渲染确实会把浏览器卡得够呛,AJAX服务器端分页+deferRender绝对是解决这个问题的最优方案,下面一步步给你讲怎么改造现有代码:

第一步:重构后端视图,支持AJAX分页查询

原来的视图是一次性把所有数据传给前端,现在我们要改成仅返回当前页需要的数据,同时支持搜索、排序这些DataTables的常用功能。

先修改你的views.py,新增一个处理AJAX请求的视图:

from django.http import JsonResponse
from django.db.models import Q
from .models import Client

# 负责返回页面(不再需要传clients数据)
def index(request):
    return render(request, 'app/index.html')

# 处理DataTables的AJAX请求,返回分页后的JSON数据
def datatable_data(request):
    # 解析DataTables发送的请求参数
    draw = int(request.GET.get('draw', 1))
    start = int(request.GET.get('start', 0))
    length = int(request.GET.get('length', 10))
    search_value = request.GET.get('search[value]', '')
    column_index = int(request.GET.get('order[0][column]', 0))
    order_dir = request.GET.get('order[0][dir]', 'asc')

    # 基础查询集,保留预取关联数据优化查询性能
    queryset = Client.objects.all().prefetch_related('loan_set', 'loan_set__case_set')

    # 处理搜索过滤(根据你的表头,搜索姓名和锁定人)
    if search_value:
        queryset = queryset.filter(
            Q(firstName__icontains=search_value) | 
            Q(lastName__icontains=search_value) |
            Q(lockedBy__icontains=search_value)
        )

    # 处理排序
    sort_columns = ['firstName', 'lastName']  # 对应表头的两列,第二列是操作列不支持排序
    if column_index < len(sort_columns):
        sort_field = sort_columns[column_index]
        if order_dir == 'desc':
            sort_field = f'-{sort_field}'
        queryset = queryset.order_by(sort_field)

    # 统计总记录数和过滤后的记录数
    total_records = Client.objects.count()
    filtered_records = queryset.count()

    # 分页截取数据
    paginated_clients = queryset[start:start+length]

    # 构造要返回的行数据(把HTML逻辑从前端移到后端)
    data = []
    csrf_token = request.META.get('CSRF_COOKIE', '')  # 获取CSRF token用于表单
    for c in paginated_clients:
        # 生成操作列的HTML
        if c.editLock:
            edit_html = f'<i class="fas fa-lock fa-lg" style="color:Red" title="W edycji przez:&nbsp;{c.lockedBy}"></i>&nbsp;{c.lockedBy}'
        else:
            edit_html = f'''<form method="post">
                                <input type="hidden" name="csrfmiddlewaretoken" value="{csrf_token}">
                                <a href="/edit/{c.pk}" name="c_id"><i class="fas fa-pen-square fa-2x" style="color:green"></i></a>
                            </form>'''
        
        data.append([
            f'{c.firstName}&nbsp;{c.lastName}',
            edit_html
        ])

    # 返回符合DataTables要求的JSON格式
    return JsonResponse({
        'draw': draw,
        'recordsTotal': total_records,
        'recordsFiltered': filtered_records,
        'data': data
    })

然后在你的urls.py里添加这个视图的路由:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('datatable-data/', views.datatable_data, name='datatable_data'),
]
第二步:修改前端模板,用AJAX加载数据

原来的模板是用Django模板循环生成所有行,现在要改成空的表格,让DataTables通过AJAX从后端拉取数据:

<table id="case_list" class="display">
    <thead>
        <tr>
            <td>Imię i nazwisko</td>
            <td>Edycja</td>
        </tr>
    </thead>
    <tbody>
        <!-- 这里留空,数据将由AJAX动态加载 -->
    </tbody>
</table>

<script type="text/javascript">
$(document).ready(function(){
    $('#case_list').DataTable({
        deferRender: true,  // 延迟渲染非当前页的行,进一步提升性能
        serverSide: true,   // 开启服务器端处理(分页、过滤、排序都交给后端)
        ajax: '{% url "datatable_data" %}',  // 对应我们新增的后端路由
        columns: [
            { data: 0 },  // 对应后端返回data数组的第一个元素(姓名)
            { data: 1, orderable: false }  // 对应操作列,设置为不可排序
        ],
        pageLength: 10,  // 默认每页显示10条
        lengthMenu: [10, 25, 50, 100],  // 让用户可选每页显示条数
        language: {  // 可选:把DataTables的提示文本改成波兰语,更贴合你的场景
            url: '//cdn.datatables.net/plug-ins/1.13.4/i18n/pl.json'
        }
    });
});
</script>
为什么这样改能解决问题?
  • 原来的方式一次性渲染3000+个DOM元素,浏览器需要大量时间解析和渲染,导致页面卡顿;现在每次只渲染当前页的10/25条,DOM数量骤减,加载速度会从15秒降到几百毫秒。
  • serverSide: true让所有分页、搜索、排序逻辑都在后端处理,前端只负责展示数据,减轻浏览器压力。
  • deferRender: true会延迟渲染不在当前视口的行,进一步减少初始加载时的DOM操作量。
额外优化建议
  • 如果你的搜索需求更复杂,可以扩展filter里的Q条件;
  • 可以给firstName和lastName字段添加数据库索引,提升搜索和排序的速度;
  • 操作列的链接如果是GET请求,其实可以去掉表单,直接用<a>标签,这样更简洁。

内容的提问来源于stack exchange,提问作者Adrian Chrostowski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:00:37