2011-08-14 67 views
6

我正在写一个管理命令,它将用建议价格过滤产品的原始价格。如何比较查询中模型的两个字段?

我有一个产品模型,它看起来像:

class Suggestion(models.Model): 
    .... 
    price = models.IntegerField() 

class Product(models.Model): 
    price = models.IntegerField() 
    suggestions = models.ManyToManyField(Suggestion) 

我要筛选其价格等于minumum建议所有产品。东西应该想:

Product.objects.filter(price = minumum(suggestions)) 

我要过滤其中的建议包含了产品的原价产品。东西应该想:

Product.objects.filter(price__in = self.suggestions) 

问题是我不能用一个for循环查找每个产品的minumum建议,因为你想我不能使用对象的自我要么,所以我怎么能比较两个查询中模型的字段?

回答

8
from django.db.models import F 
Product.objects.filter(price__in=F('suggestions')) 
+1

谢谢!这很好。然而,有一个小错误:建议必须用F('建议')中的引号标出。 –

2
  • Product.objects.filter(price = minumum(suggestions))

suggestions不是(传递给F应该有引号,像F('suggestions')F(suggestions)和列)的产品领域。所以这不好。

对此的原始SQL是这样的,它加入到一个子查询中,获得每个产品的最低价格,然后将列表过滤为价格==最低价格的产品。

SELECT * FROM product 
    LEFT JOIN (
    SELECT _products_suggestions.product_id, MIN(price) as min_price 
    FROM suggestion 
    RIGHT JOIN _products_suggestions 
    GROUP BY _products_suggestions.product_id 
    ) AS min_suggestions ON min_suggestions.product_id = product.id 
    WHERE product.price = min_suggestions.price 

您不能以这种方式使用django ORM执行自定义连接(自1.4开始)。您将需要使用raw SQL query

  • Product.objects.filter(price__in = self.suggestions)

self.suggestions,假设我们是在一个例如Product方法,是不是列表,到目前为止,它是一个RelatedSetManager。不过,我怀疑你想获得所有具有当前(又名self)产品的建议价格之一的产品。这似乎很奇怪。

它听起来像你想要的是一个产品的列表,其中有一个建议匹配一个的建议价格。

您将再次需要原始SQL。 : -/

SELECT * FROM product 
    LEFT JOIN _products_suggestions ON _products_suggestions.product_id = product.id 
    LEFT JOIN suggestion ON _products_suggestions.suggestion_id = suggestion.id 
    WHERE suggestion.price = product.price 

这样做,我想。 RIGHT JOIN可能会更快,我不确定,但无论如何,你最终会得到一个价格相同的产品和建议清单。