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
相关产品推荐
相关产品推荐

