从ForeignKey关系中仅连接一行的查询

时间:2012-10-04 18:29:36

标签: sql django

我有以下模型(简化):

class Category(models.model):
    # ...

class Product(models.model):
    # ...

class ProductCategory(models.Model):
    product = models.ForeignKey(Product)
    category = models.ForeignKey(Category)
    # ...

class ProductImage(models.Model):
    product = models.ForeignKey(Product)
    image = models.ImageField(upload_to=product_image_path)
    sort_order = models.PositiveIntegerField(default=100)
    # ...

我想构建一个查询,以获取与特定类别相关联的所有产品。我想在查询集中仅包含许多相关图像的一个 - 具有最低sort_order的图像 - 以便单个查询获得显示所有产品所需的所有数据在一个类别中。

在原始SQL中,我可能会使用GROUP BY这样的东西:

SELECT * FROM catalog_product p 
LEFT JOIN catalog_productcategory c ON (p.id = c.product_id) 
LEFT JOIN catalog_productimage i ON (p.id = i.product_id) 
WHERE c.category_id=2 
GROUP BY p.id HAVING i.sort_order = MIN(sort_order)

这可以在不使用原始查询的情况下完成吗?

编辑 - 我应该注意到我的尝试......

# inside Category model...
products = Product.objects.filter(productcategory__category=self) \
            .annotate(Min('productimage__sort_order'))

虽然此查询执行GROUP BY,但我没有看到任何方法(a)将正确的ProductImage.image放入QuerySet中,例如。 HAVING条款。我正在尝试从特定的ProductImage实例向Product实例(或QuerySet)动态添加字段。这可能不是使用Django的方法。

2 个答案:

答案 0 :(得分:0)

这不是一个原始的查询,但它也不是公开的api。

您可以在评估之前将group by子句添加到查询集:

qs = Product.objects.filter(some__foreign__key__join=something)
qs.group_by = 'some_field'
results = list(qs)

谨慎之处:根据数据库后端,这种行为会有所不同。

答案 1 :(得分:0)

catagory = Catagory.objects.get(get_your_catagory)
qs = Product.objects.annotate(Min('productimage__sortorder').filter(productcategory__category = catagory)

这应该只对数据库命中一次,因为查询集是懒惰的。