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

如何在Django首页按商品分类分组逐行展示对应商品

问题根源

原有代码直接遍历全量商品,每读取一个商品就渲染一次分类标题,会导致同一分类标题重复出现、同分类商品被拆分到多个标题下,无法实现分类聚合展示的效果。正确逻辑是先遍历所有商品分类,再在每个分类区块内渲染该分类关联的全部商品。

具体实现方案

1. 修改视图层逻辑

不需要直接把全量商品传入模板,改为查询所有分类,同时通过预加载关联数据的方式避免数据库N+1查询问题,性能更好。
替换views.py中home视图的代码:

from .models import Category, Products

def home(request):
    # 查询全部分类,同时预加载每个分类下的关联商品
    categories = Category.objects.prefetch_related("categoty_related_name").all()
    context = {
        "categories": categories
    }
    return render(request, 'home.html', context)

说明:你之前在context_processors中已经注入了categories变量,但视图层传递的同名变量会覆盖它,直接在视图中做预加载处理可以减少不必要的数据库查询,性能更优。

2. 模型层说明

你的现有模型不需要修改,仅需注意:你在Products模型的外键中配置了related_name="categoty_related_name"(存在拼写失误,正确拼写应为category,但不影响功能运行),后续代码统一使用你已经定义的这个关联名即可,每个Category实例都可以通过.categoty_related_name.all()获取该分类下的所有商品。

3. 修改模板层代码

将原有遍历全量商品的单层循环,改为「外层遍历分类、内层遍历分类下商品」的两层嵌套循环。
替换模板中原有循环部分的代码:

{% for category in categories %}
<!-- 分类标题区块 -->
<h4 class="text-start montserrat_alternates_font">{{ category.title }}</h4>
<hr>

<!-- 遍历渲染当前分类下的所有商品 -->
{% for product in category.categoty_related_name.all %}
<!--- product card --->
<div class="col mb-5">
    <div class="card h-100">

        <!-- Sale badge-->
        {% if product.offer_price != None %}
        <div class="badge bg-dark text-white position-absolute" style="top: 0.5rem; right: 0.5rem">
            SALE
        </div>
        {% endif %}

        <!-- Product image-->
        <img class="card-img-top" style="height:150px;" src="{{product.product_image.url}}" alt="商品图片" />
        <!-- Product details-->
        <div class="card-body ">
            <div class="text-center">
                <!-- Product name-->
                <h5 class="fw-bolder product_title">{{product.product_title}}</h5>
                <!-- 可自行补充商品价格、折扣价等字段的渲染逻辑 -->
            </div>
        </div>

    </div>
</div>
{% endfor %}
<!-- 单个分类商品渲染完成,自动进入下一个分类的循环 -->
{% endfor %}
可选优化
  • 如果需要隐藏没有任何商品的空分类,可以修改视图中的分类查询逻辑:
    categories = Category.objects.prefetch_related("categoty_related_name").filter(categoty_related_name__isnull=False).distinct()
    
  • 如果需要对分类下的商品排序(比如按创建时间倒序),可以在预加载时指定排序规则:
    from django.db.models import Prefetch
    
    categories = Category.objects.prefetch_related(
        Prefetch("categoty_related_name", queryset=Products.objects.order_by("-created_date"))
    ).all()
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 22:06:12