如何在查询中比较模型的两个字段?

时间:2011-08-14 00:22:53

标签: django filter compare aggregate-functions

我正在编写一个管理命令,它会根据建议的价格过滤产品的原始价格。

我的产品型号如下:

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

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

我想过滤所有价格等于最低建议的产品。有点像:

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

我想过滤建议中包含产品原始价格的产品。有点像:

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

问题是我不能使用for循环来查看每个产品的最小建议,因为你猜我也不能使用对象的 self ,所以如何比较a的两个字段?查询中的模型?

2 个答案:

答案 0 :(得分:10)

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

答案 1 :(得分:2)

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

suggestions不是Product上的字段(传递给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,假设我们 in 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可能会更快,我不确定,但无论如何,你最终会得到一份价格相同的产品和建议清单。