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

Flask中Datatable渲染过慢如何优化?PG表含35k+行

优化Datatable渲染35k+数据的性能方案

嘿,遇到35k+数据在Datatable里渲染慢的问题太常见了——本质原因是一次性把上万行DOM节点塞进浏览器,浏览器根本处理不过来。我给你几个从易到难的优化方案,你可以按需尝试:

1. 启用内置分页+延迟渲染(最快见效的轻量优化)

这是最简单的改法,不需要动后端,只调整Datatable的配置。默认情况下如果没开分页,Datatable会一次性渲染所有行,开分页后每次只渲染当前页的内容,DOM节点数直接降到几十/几百级。

修改你的JS代码:

var html_one = $('#html_one').DataTable({
    select: true,
    fixedHeader: true,
    paging: true, // 强制开启分页(默认可能已开,但明确写出来更保险)
    pageLength: 100, // 每页显示100条,可根据你的需求调整(比如50/200)
    deferRender: true, // 延迟渲染未显示的行,进一步减少初始化时的DOM操作
    lengthMenu: [50, 100, 200, 500] // 给用户提供每页条数选择
});

同时,你可以在初始化前先隐藏表格,避免页面卡顿:

<div class="col-sm-12">
    {% for table in tables %}
        <div style="display:none;" id="table-container">
            {{ table|safe }}
        </div>
    {% endfor %}
</div>

然后在JS初始化完成后显示:

var html_one = $('#html_one').DataTable({
    // 你的配置...
    initComplete: function() {
        $('#table-container').show();
    }
});

2. 改用服务器端分页(处理超大数据的终极方案)

如果分页后还是觉得前端压力大,或者未来数据会增长到10w+级别,就把分页、过滤、排序的逻辑放到后端(Flask)来做,前端只请求当前页的数据。这样前端永远只渲染几十行,性能拉满。

步骤1:后端写一个Datatable数据接口

修改你的app.py,新增一个接口专门处理Datatable的请求:

from flask import jsonify, request

# 建议缓存API数据,避免每次请求都调用外部API(太耗时)
# 可以用Flask的全局变量或者Redis,这里用全局变量示例
communes_df = None

@app.route('/html_one', methods=["POST","GET"])
def referentiel_communes():
    global communes_df
    if communes_df is None:
        r = requests.get('https://api/', params=payload, verify=False)
        data_dict = r.json()
        communes_df = pd.read_json(json.dumps(data_dict))
    # 现在只返回表头,表格由前端Datatable动态渲染
    return render_template('referentiel_communes.html', titles=communes_df.columns.values)

@app.route('/datatable_communes', methods=['POST'])
def datatable_communes():
    global communes_df
    # 获取Datatable发送的参数(这些是Datatable自动传的)
    draw = int(request.form.get('draw', 1))
    start = int(request.form.get('start', 0))
    length = int(request.form.get('length', 10))
    search_val = request.form.get('search[value]', '').strip()

    # 复制一份数据避免修改原缓存
    df = communes_df.copy()

    # 搜索过滤(如果用户输入了搜索词)
    if search_val:
        # 模糊匹配所有列,你可以调整成只匹配特定列提升速度
        df = df[df.apply(lambda row: any(search_val.lower() in str(cell).lower() for cell in row), axis=1)]
    
    # 统计总数
    total = df.shape[0]
    # 分页切片
    df_page = df.iloc[start:start+length]

    # 整理成Datatable要求的JSON格式
    response = {
        "draw": draw,
        "recordsTotal": communes_df.shape[0],
        "recordsFiltered": total,
        "data": df_page.to_dict('records')
    }
    return jsonify(response)

步骤2:修改前端HTML和JS

把原来的静态表格改成空表格,由Datatable动态拉取数据:

<div class="col-sm-12">
    <table id="html_one" class="display table table-striped table-bordered">
        <thead>
            <tr>
                {% for col in titles %}
                <th>{{ col }}</th>
                {% endfor %}
            </tr>
        </thead>
        <tbody></tbody>
    </table>
</div>

修改JS配置,启用服务器端模式:

var html_one = $('#html_one').DataTable({
    select: true,
    fixedHeader: true,
    serverSide: true, // 开启服务器端处理
    ajax: {
        url: '/datatable_communes',
        type: 'POST'
    },
    columns: [
        // 自动映射每个列,和后端返回的data字段对应
        {% for col in titles %}
        { data: '{{ col }}' },
        {% endfor %}
    ],
    pageLength: 100,
    lengthMenu: [50, 100, 200]
});

3. 其他小优化

  • 关闭不必要的功能:如果你不需要select或者fixedHeader,可以暂时关掉它们,减少Datatable的计算量;
  • 优化列配置:给不需要排序的列加上orderable: false,避免Datatable做无用的排序计算;
  • 减少DOM元素:如果表格里有复杂的HTML元素(比如按钮、链接),尽量简化,或者用Datatable的column.render动态生成,避免提前渲染大量元素。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 07:48:12