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

基于单个Model实现网站首页嵌套分类菜单展示求助

Django嵌套分类菜单实现方案

一、模型优化(可选但推荐)

在ProductCategory模型中补充关联名称,方便后续查询子分类,也可添加自定义方法统一子分类排序逻辑:

class ProductCategory(models.Model):
    name = models.CharField(max_length=50, blank=True, null=True)
    # 补充related_name,让子分类查询更直观
    parent_category = models.ForeignKey(
        'self', null=True, blank=True, on_delete=models.CASCADE, related_name='children')
    category_image = models.ImageField(
        upload_to='categories/product/imgs/', verbose_name=_("Category Image"), blank=True, null=True,
        help_text=_("Please use our recommended dimensions: 120px X 120px"))
    category_description = models.TextField(verbose_name=_("Category Description"))
    slug = models.SlugField(
        blank=True, null=True, allow_unicode=True, unique=True, verbose_name=_("Slugfiy"))
    date = models.DateTimeField(auto_now_add=True, blank=True, null=True)

    def get_sorted_children(self):
        # 返回按名称排序的子分类
        return self.children.order_by('name')

二、视图层处理

在首页视图中获取所有顶级分类(无父分类的),并通过预加载避免N+1查询问题:

from django.shortcuts import render
from .models import ProductCategory
from django.db.models import Prefetch

def home(request):
    # 预加载排序后的子分类,减少数据库查询次数
    top_categories = ProductCategory.objects.filter(parent_category__isnull=True).prefetch_related(
        Prefetch('children', queryset=ProductCategory.objects.order_by('name'))
    ).order_by('name')
    return render(request, 'home.html', {'top_categories': top_categories})

三、模板递归渲染

1. 首页主模板(home.html)

在首页指定位置引入分类菜单的递归子模板:

<!-- 首页分类菜单区域 -->
<div class="category-menu">
    <ul class="main-category-list">
        {% for category in top_categories %}
            {% include 'components/category_item.html' with category=category %}
        {% endfor %}
    </ul>
</div>

2. 递归子模板(components/category_item.html)

创建独立子模板处理单个分类及其嵌套子分类的渲染:

<li class="category-item">
    <a href="{% url 'category_detail' category.slug %}" class="category-link">
        {% if category.category_image %}
            <img src="{{ category.category_image.url }}" alt="{{ category.name }}" class="category-icon">
        {% endif %}
        <span>{{ category.name }}</span>
    </a>
    <!-- 存在子分类时,递归渲染子菜单 -->
    {% if category.children.exists %}
        <ul class="subcategory-list">
            {% for subcat in category.children.all %}
                {% include 'components/category_item.html' with category=subcat %}
            {% endfor %}
        </ul>
    {% endif %}
</li>

四、基础样式示例(可选)

添加CSS让嵌套菜单层级更清晰:

.category-menu ul {
    list-style: none;
    padding-left: 0;
}

.main-category-list > .category-item {
    margin: 10px 0;
}

.category-link {
    display: flex;
    align-items: center;
    gap: 8px;
    text-decoration: none;
    color: #2d3748;
    padding: 6px 0;
}

.category-icon {
    width: 32px;
    height: 32px;
    object-fit: cover;
    border-radius: 4px;
}

.subcategory-list {
    padding-left: 24px;
    margin-top: 4px;
    border-left: 1px solid #e2e8f0;
}

.subcategory-list .category-link {
    font-size: 0.9em;
}

五、实用优化点

  • 缓存分类数据:分类数据更新频率低,可通过Django缓存框架缓存top_categories查询结果,减少数据库压力。
  • 空值安全处理:模板中对name、category_image等字段添加空值判断,避免页面渲染报错。
  • 排序配置:可在模型中添加ordering元组,统一分类的默认排序规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 15:22:46