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

Django如何实现按分类、品牌层级分组展示商品列表

Django 按分类品牌层级展示商品列表解决方案

问题根因

你当前实现直接将全量品牌数据传入模板,遍历逻辑未过滤「当前分类下无对应商品的品牌」,因此会出现空品牌展示的问题,同时模板层嵌套全量遍历加条件判断的写法会产生大量无效运算,查询效率极低。

最优实现方案

方案1:视图层预处理嵌套结构(新手友好,无额外学习成本)

直接在视图层构造好「分类-当前分类下有商品的品牌-对应商品」的三层嵌套结构,模板仅需遍历渲染即可,无需任何条件判断。

views.py 代码

def product_list(request):
    # 构造三级嵌套结构
    category_nested_data = []
    for category in Category.objects.all():
        # 仅查询当前分类下有商品的品牌,自动去重
        related_brands = Brand.objects.filter(product__category=category).distinct()
        brand_list = []
        for brand in related_brands:
            # 查询当前分类+当前品牌下的所有商品
            related_products = Product.objects.filter(category=category, brand=brand)
            brand_list.append({
                "obj": brand,
                "products": related_products
            })
        category_nested_data.append({
            "obj": category,
            "brands": brand_list
        })
    
    context = {
        "category_nested_data": category_nested_data
    }
    return render(request, "product/product-list.html", context)

product-list.html 模板代码

<ul>
    {% for category_item in category_nested_data %}
    <li>{{ category_item.obj }}</li>
    <ul>
        {% for brand_item in category_item.brands %}
        <li>{{ brand_item.obj }}</li>
        <ul>
            {% for product in brand_item.products %}
            <li>{{ product }}</li>
            {% endfor %}
        </ul>
        {% endfor %}
    </ul>
    {% endfor %}
</ul>

方案2:ORM 预加载优化版(适合数据量较大的场景)

使用 Django 内置的 Prefetch 预加载关联数据,大幅减少数据库查询次数,提升性能。

views.py 代码

from django.db.models import Prefetch

def product_list(request):
    # 预加载商品关联
    product_prefetch = Prefetch(
        "product_set",
        queryset=Product.objects.all()
    )
    # 预加载当前分类下有商品的品牌,同时关联对应商品
    category_prefetch = Prefetch(
        "brand_set",
        queryset=Brand.objects.filter(
            product__isnull=False
        ).prefetch_related(product_prefetch).distinct()
    )
    categories = Category.objects.prefetch_related(category_prefetch).all()

    context = {
        "categories": categories
    }
    return render(request, "product/product-list.html", context)

product-list.html 模板代码

<ul>
    {% for category in categories %}
    <li>{{ category }}</li>
    <ul>
        {% for brand in category.brand_set.all %}
        <li>{{ brand }}</li>
        <ul>
            {% for product in brand.product_set.all %}
            {% if product.category == category %}
            <li>{{ product }}</li>
            {% endif %}
            {% endfor %}
        </ul>
        {% endfor %}
    </ul>
    {% endfor %}
</ul>

额外优化提示

你当前的 Category 模型 __str__ 方法返回的是 category_id,如果要和你预期的展示效果对齐显示分类名称,可以把该方法修改为:

def __str__(self):
    return self.name

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 03:15:03