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

如何在Django首页获取每个分类下的3条产品记录?

解决Django中每个分类取3条产品的问题

先明确你代码里的几个核心问题:

  • 模型名拼写错误:Produc应该改为Product,查询时的Products也要对应改成Product
  • 循环中每次覆盖que变量,最终只会返回最后一个分类的产品,无法获取所有分类的结果
  • cat[..]写法错误,获取分类ID应该用cat.id,或者直接用category=cat更直观
  • 直接循环查询会产生N+1数据库请求,性能表现较差

方法一:整理分类与对应产品的列表(简单直观)

修改homepro逻辑,把每个分类和它的3条产品存成字典列表,方便模板渲染:

class Category(models.Model):
    name = models.CharField(max_length=100)  # 补充完整字段定义

class Product(models.Model):
    name = models.CharField(max_length=100)
    category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name="products")  # 补充related_name简化反向查询

class Home_Cls(TemplateView):
    template_name = "home.html"  # 配置你的首页模板路径

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # 构建分类与对应产品的列表
        category_products = []
        for cat in Category.objects.all():
            # 通过related_name反向查询分类下的产品,随机取3条
            top_products = cat.products.order_by('?')[:3]
            category_products.append({"category": cat, "products": top_products})
        context["category_products"] = category_products
        return context

模板中可以这样遍历渲染:

{% for item in category_products %}
    <h3>{{ item.category.name }}</h3>
    <ul>
        {% for product in item.products %}
            <li>{{ product.name }}</li>
        {% endfor %}
    </ul>
{% endfor %}

方法二:用Subquery优化查询(避免N+1问题)

如果分类数量较多,方法一的循环会触发多次数据库查询,用Subquery和OuterRef可以实现一次查询完成所有数据获取:

from django.db.models import OuterRef, Subquery, Prefetch

class Home_Cls(TemplateView):
    template_name = "home.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # 子查询:获取每个分类下的3条随机产品ID
        product_subquery = Product.objects.filter(
            category=OuterRef('pk')
        ).order_by('?')[:3].values_list('pk', flat=True)
        
        # 给分类添加关联产品字段,同时预取对应产品
        categories = Category.objects.annotate(
            product_ids=Subquery(product_subquery)
        ).prefetch_related(
            Prefetch(
                'products', 
                queryset=Product.objects.filter(pk__in=OuterRef('product_ids')), 
                to_attr='top_products'
            )
        )
        
        context["categories"] = categories
        return context

模板中遍历方式:

{% for category in categories %}
    <h3>{{ category.name }}</h3>
    <ul>
        {% for product in category.top_products %}
            <li>{{ product.name }}</li>
        {% endfor %}
    </ul>
{% endfor %}

注意:order_by('?')在MySQL中性能较差,如果不需要完全随机,可以换成按创建时间倒序取最新3条(order_by('-id')[:3])来优化性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 04:05:01