如何优化Django项目中HR列表页的加载速度?
Django HR列表页加载优化方案
针对1200条数据加载耗时近10秒的问题,核心优化方向是解决ORM查询的N+1问题,辅以分页、缓存等手段,具体方案如下:
1. 解决N+1查询问题(核心优化)
当前ListView默认的queryset会触发N+1查询:加载1200条HR数据后,模板渲染时每访问一个外键字段(如year_scenario_version)都会单独发起一次数据库请求,累计产生大量重复查询,这是耗时的主要原因。
修改views.py,使用select_related预加载所有关联的外键对象,将多次查询合并为一次:
class HRListView(Budgetlevel2Mixin, BudgetMixin, LoginRequiredMixin, ListView): model = HR template_name = "budget/hr_list.html" # 预加载所有外键关联对象,避免N+1查询 queryset = HR.objects.select_related( 'year_scenario_version', 'measure_name', 'employee_type', 'employee_level', 'subsidiary', 'department', 'currency' # 模型中定义的外键,即使模板未用到也建议预加载避免后续风险 )
如果需要动态调整查询条件,可重写get_queryset方法:
def get_queryset(self): return super().get_queryset().select_related( 'year_scenario_version', 'measure_name', 'employee_type', 'employee_level', 'subsidiary', 'department', 'currency' )
2. 分页处理
一次性渲染1200条数据会增加DOM渲染时间,同时加大数据库查询压力。通过分页将数据拆分,每次仅加载部分数据:
修改views.py添加分页配置:
class HRListView(Budgetlevel2Mixin, BudgetMixin, LoginRequiredMixin, ListView): model = HR template_name = "budget/hr_list.html" queryset = HR.objects.select_related(...) # 保留上述预加载配置 paginate_by = 20 # 每页显示20条,可根据需求调整
在hr_list.html末尾添加分页导航:
{% block pagination %} {% if is_paginated %} <div class="pagination"> <span class="page-links"> {% if page_obj.has_previous %} <a href="?page={{ page_obj.previous_page_number }}">上一页</a> {% endif %} <span class="page-current"> 第 {{ page_obj.number }} 页 / 共 {{ page_obj.paginator.num_pages }} 页 </span> {% if page_obj.has_next %} <a href="?page={{ page_obj.next_page_number }}">下一页</a> {% endif %} </span> </div> {% endif %} {% endblock %}
3. 模板缓存优化(可选)
如果HR数据不是实时更新,可通过模板缓存减少重复渲染耗时:
在hr_list.html顶部加载缓存标签,并缓存整个列表区域:
{% load cache %} <!-- 缓存5分钟,按用户ID区分缓存(如果不同用户看到的数据不同) --> {% cache 300 hr_list request.user.id %} {% block thead %} <!-- 原表头代码 --> {% endblock %} {% block tbody %} <!-- 原表体循环代码 --> {% endblock %} {% block pagination %} <!-- 分页代码 --> {% endblock %} {% endcache %}
4. 数据库索引检查
确认HR模型的所有外键字段已创建索引(Django默认会为ForeignKey自动创建索引,但若手动修改过模型需验证)。若有常用的排序/过滤字段,可额外添加索引以加速查询。
内容的提问来源于stack exchange,提问作者user13719970
相关产品推荐
相关产品推荐

