如何在Django模板中对多层一对多关系模型实现嵌套循环
Django模板中实现Track→Tees→HoleInfo的嵌套循环展示高尔夫球场球洞信息
你的核心问题在于当前视图查询返回的是扁平化的HoleInfo对象集合,无法直接在模板中按Track和Tees分组循环。需要先调整视图的查询逻辑,再配合模板的嵌套循环实现需求。
1. 优化视图查询逻辑
从GolfCourse对象入手,通过prefetch_related预取所有关联层级的数据,避免N+1查询问题,同时让数据结构更贴合模板的嵌套需求:
from django.shortcuts import get_object_or_404, render from .models import GolfCourse def course_detail(request, pk): # 获取指定球场,预取关联的Track、Tees及对应的球洞信息 course = get_object_or_404( GolfCourse.objects.prefetch_related( 'track_set__tees_set__holeinfo_set' ), pk=pk ) return render(request, 'course_detail.html', {'course': course})
2. 模板嵌套循环实现分组展示
基于优化后的查询结果,在模板中通过三层循环实现球场→球道(Track)→发球台(Tees)→球洞(HoleInfo)的层级展示:
<h1>{{ course.name }}</h1> {% for track in course.track_set.all %} <h2>球道:{{ track.name }}</h2> {% for tee in track.tees_set.all %} <h3>发球台:{{ tee.name }} (评分: {{ tee.rating }}, 坡度: {{ tee.slope }})</h3> <!-- 球洞信息表格 --> <table border="1" cellpadding="8" cellspacing="0"> <thead> <tr> <th>球洞编号</th> <th>标准杆</th> <th>难度系数</th> <th>码数</th> </tr> </thead> <tbody> <!-- 按球洞编号排序展示 --> {% for hole in tee.holeinfo_set.all|dictsort:"hole_number" %} <tr> <td>{{ hole.hole_number }}</td> <td>{{ hole.par }}</td> <td>{{ hole.handicap }}</td> <td>{{ hole.yardage }}</td> </tr> {% endfor %} </tbody> </table> {% endfor %} {% endfor %}
可选优化:给外键设置更直观的关联名称
可以在模型的ForeignKey字段中添加related_name参数,让模板代码更易读:
# Track模型 class Track(models.Model): course_id = models.ForeignKey(GolfCourse, on_delete=models.CASCADE, related_name='tracks') # ...其他字段 # Tees模型 class Tees(models.Model): track_id = models.ForeignKey(Track, on_delete=models.CASCADE, related_name='tees') # ...其他字段 # HoleInfo模型 class HoleInfo(models.Model): tee_id = models.ForeignKey(Tees, on_delete=models.CASCADE, related_name='holes') # ...其他字段
修改后模板中的循环可以简化为:
{% for track in course.tracks.all %} {% for tee in track.tees.all %} {% for hole in tee.holes.all|dictsort:"hole_number" %} <!-- 球洞内容 --> {% endfor %} {% endfor %} {% endfor %}
内容的提问来源于stack exchange,提问作者ND24
相关产品推荐
相关产品推荐

