Django按状态分块划分模板 多for循环查询实现方案
结论
不要在模板层实现这类分组查询逻辑。Django模板的定位是仅负责展示层轻量渲染,本身被刻意限制了复杂数据处理能力,这类分组需求放在视图层配合ORM实现,查询效率更高、代码可维护性也更好。
具体实现方案
先给出参考模型定义,方便对齐逻辑:
# models.py from django.db import models class State(models.Model): # 状态编号,对应你提到的状态1、2、3 code = models.IntegerField(unique=True) name = models.CharField(max_length=50, blank=True) def __str__(self): return f"Status {self.code}" class Project(models.Model): name_title_working = models.CharField(max_length=200) fk_state = models.ForeignKey(State, on_delete=models.PROTECT, related_name="projects") genre = models.CharField(max_length=100) d_conceived = models.DateField()
方案1:通过外键反向关联实现(推荐)
这个方案可以自动覆盖所有状态,哪怕某个状态下暂时没有项目也能正常渲染出对应标题,还能通过预加载避免N+1查询问题。
视图层代码:
# views.py from django.shortcuts import render from .models import State def project_list(request): # prefetch_related会一次性预加载所有状态关联的项目,不会重复查库 states = State.objects.prefetch_related("projects").all().order_by("code") return render(request, "project_list.html", {"states": states})
模板层代码完全不需要写查询逻辑,直接循环渲染即可:
<h1 class="main_title">Projects</h1> {% for state in states %} <h2>Projects with a Status of {{ state.code }}</h2> {% for project in state.projects.all %} <h3>> {{ project.name_title_working }}</h3> <p>> {{ project.fk_state }}</p> <p>> {{ project.genre }}</p> <p>> {{ project.d_conceived }}</p> {% empty %} <p>当前状态下暂无项目</p> {% endfor %} {% endfor %}
方案2:分组聚合实现(仅展示有项目的状态)
如果不需要展示没有对应项目的空状态,可以在视图层对项目查询结果直接分组:
# views.py from django.shortcuts import render from itertools import groupby from .models import Project def project_list(request): # 注意:用groupby必须先按分组字段排序,否则会出现分组错误 projects = Project.objects.select_related("fk_state").order_by("fk_state__code") project_groups = {} for state, group_items in groupby(projects, key=lambda x: x.fk_state): project_groups[state] = list(group_items) return render(request, "project_list.html", {"project_groups": project_groups})
对应模板:
<h1 class="main_title">Projects</h1> {% for state, projects in project_groups.items %} <h2>Projects with a Status of {{ state.code }}</h2> {% for project in projects %} <h3>> {{ project.name_title_working }}</h3> <p>> {{ project.fk_state }}</p> <p>> {{ project.genre }}</p> <p>> {{ project.d_conceived }}</p> {% endfor %} {% endfor %}
为什么不推荐在模板层硬写逻辑
- 模板没有原生分组能力,硬要实现需要写大量重复判断逻辑,会触发多次数据库查询,产生严重的N+1性能问题
- 业务逻辑和展示逻辑强耦合,后续要调整分组规则、增加筛选条件时维护成本极高
- 就算通过自定义模板标签实现,本质上还是把数据处理逻辑挪到了标签层,不如直接在视图层处理清晰直观。
内容的提问来源于stack exchange,提问作者Game Analysis
相关产品推荐
相关产品推荐

