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

如何在Django模板中访问外键?分类层级显示异常求助

修复Django三级分类模板显示问题

问题背景

定义了主分类、分类、子分类三级关联模型,视图已将主分类查询集传递至模板,但仅主分类能正常展示,分类和子分类无法显示。

模型代码

class MainCategory(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self) :
        return self.name
    
class Category(models.Model):
    main_category = models.ForeignKey(MainCategory, on_delete=models.CASCADE, related_name="maincategory")
    name = models.CharField(max_length=100)

    def __str__(self) :
        return self.name + "--" + self.main_category.name
    
class SubCategory(models.Model):
    category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name="category_name")
    name = models.CharField(max_length=100)

    def __str__(self) :
        return self.name

原视图代码

def Home(request):
    sliders = Slider.objects.all()
    banners = BannerArea.objects.all()
    main_category = MainCategory.objects.all()
    context = {
        'sliders' : sliders,
        'banners' : banners,
        'main_category' : main_category
    }
    return render(request, 'main/home.html', context)

原模板代码

<div class="cat__menu">
    <nav id="mobile-menu" style="display: block;">
        <ul>
            {% for i in main_category %}
            <li>
                <a href="shop.html"> {{ i.name }} <i class="far fa-angle-down"></i></a>
                <ul class="mega-menu">
                    {% for cat in i.category_set.all %}
                    <li><a href="shop.html">{{cat.name}}</a>
                        <ul class="mega-item">
                            {% for sub_cat in cat.subcategory_set.all %}
                            <li><a href="product-details.html">{{sub_cat.name}}</a></li>
                            {% endfor %}
                        </ul>
                    </li>
                    {% endfor %}
                </ul>
            </li>
            {% endfor %}
        </ul>
    </nav>
</div>

修复方案

1. 修正模板中的关联查询名称

模型定义时已指定related_name,因此不能使用Django默认的xxx_set语法,需改用自定义的关联名称:

  • 主分类获取分类:将i.category_set.all()改为i.maincategory.all()(对应Category模型的related_name="maincategory")
  • 分类获取子分类:将cat.subcategory_set.all()改为cat.category_name.all()(对应SubCategory模型的related_name="category_name")

2. 优化查询性能(可选但推荐)

为避免模板中出现N+1查询问题,在视图中使用prefetch_related预加载关联数据:

def Home(request):
    sliders = Slider.objects.all()
    banners = BannerArea.objects.all()
    # 预加载分类和子分类,减少数据库查询次数
    main_category = MainCategory.objects.prefetch_related('maincategory__category_name').all()
    context = {
        'sliders' : sliders,
        'banners' : banners,
        'main_category' : main_category
    }
    return render(request, 'main/home.html', context)

修复后的模板代码

<div class="cat__menu">
    <nav id="mobile-menu" style="display: block;">
        <ul>
            {% for i in main_category %}
            <li>
                <a href="shop.html"> {{ i.name }} <i class="far fa-angle-down"></i></a>
                <ul class="mega-menu">
                    {% for cat in i.maincategory.all %}
                    <li><a href="shop.html">{{cat.name}}</a>
                        <ul class="mega-item">
                            {% for sub_cat in cat.category_name.all %}
                            <li><a href="product-details.html">{{sub_cat.name}}</a></li>
                            {% endfor %}
                        </ul>
                    </li>
                    {% endfor %}
                </ul>
            </li>
            {% endfor %}
        </ul>
    </nav>
</div>

内容的提问来源于stack exchange,提问作者user21878286

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 15:17:22