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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 07:49:58