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

如何在Django中获取外键关联的指定分类下全部产品?

优化获取指定分类下产品的方法

问题描述

目标:从自建模型中获取属于特定分类的所有条目,例如通过分类ID获取该分类下的所有产品。

模型代码

Product模型:

class Product(models.Model):
    name = models.CharField(max_length=200)
    category = models.ForeignKey('Category', null=True, on_delete=models.SET_NULL)
    id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)

    def __str__(self):
        return self.name

Category模型:

class Category(models.Model):
    #product = models.ForeignKey('Product', null=True, on_delete=models.SET_NULL)
    name = models.CharField(max_length=200, blank=True, null=True)
    id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)

    def __str__(self):
        return self.name

当前实现

视图代码:

def getCategory(request, pk):
    category = Category.objects.get(id=pk)
    products = Product.objects.all()
    context = {'category': category, 'products':products}
    return render(request, 'products/shop.html', context)

模板代码:

{% for product in products %}
{% if product.category.id == category.id %}
    <!-- 产品内容渲染 -->
{% endif %}
{% endfor %}

疑问:尝试用Product.category_set.all()未成功,想了解更优实现方法。


更优实现方法

方法1:正确使用Django反向关联查询

你之前误用了反向查询的调用方式——反向关联是从Category实例触发,而非Product模型。因为外键定义在Product上,Django默认给Category生成的反向关联名为product_set(模型名小写+_set),正确写法如下:

def getCategory(request, pk):
    category = Category.objects.get(id=pk)
    # 直接获取该分类下的所有关联产品
    products = category.product_set.all()
    context = {'category': category, 'products':products}
    return render(request, 'products/shop.html', context)

模板无需再做ID判断,直接遍历即可:

{% for product in products %}
    <!-- 产品内容渲染 -->
{% endfor %}

如果觉得product_set不够直观,可以在Product的外键字段中指定related_name:

category = models.ForeignKey('Category', null=True, on_delete=models.SET_NULL, related_name='products')

之后就能用category.products.all()来获取关联产品,语义更清晰。

方法2:直接过滤Product模型

通过Product的category字段直接过滤,也是高效的实现方式:

def getCategory(request, pk):
    category = Category.objects.get(id=pk)
    # 两种过滤方式二选一
    products = Product.objects.filter(category__id=pk)
    # 或用category实例过滤:products = Product.objects.filter(category=category)
    context = {'category': category, 'products':products}
    return render(request, 'products/shop.html', context)

方法3:优化查询避免N+1问题

如果后续需要访问产品关联的分类信息,或分类的其他字段,可以用select_related(正向外键查询)或prefetch_related(反向关联查询)减少数据库请求次数:

  • 反向关联场景:
category = Category.objects.prefetch_related('product_set').get(id=pk)
products = category.product_set.all()
  • 过滤查询场景:
products = Product.objects.select_related('category').filter(category__id=pk)

这样能避免遍历产品时,每次都发起一次分类查询的低效问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 06:00:59