带注释的Django过滤器

时间:2012-03-21 07:52:24

标签: python django django-queryset

class Review(models.Model):
    slug = models.SlugField(max_length=255, unique=True)
    vendor = models.ForeignKey(Vendor)
    user = models.ForeignKey(User, blank=True, null=True)
    product = models.ForeignKey(Product, blank=True, null=True)
    images = models.ManyToManyField(ReviewImage, blank=True, null=True)
    headline = models.CharField(max_length=100)
    review = models.TextField(blank=True, null=True)
    rating = models.IntegerField()
    active = models.BooleanField(default=1)
    created = models.DateTimeField(auto_now_add=True)
    changed = models.DateTimeField(auto_now=True)

# This is the problem... I works, but no vendor is shown if there is no review.
vendor_list = (Vendor.objects.filter(category=category,
                                     review__product__isnull=True,
                                     active=True)
               .annotate(rating_avg=Avg('review__rating')))

我如何使用review__product__isnull=True执行此操作?如果根本没有评论,我仍然想要供应商,但评级应该是:“0”,...该怎么办?

2 个答案:

答案 0 :(得分:1)

让我们看看我是否理解这一点。您正尝试列出该类别中的所有活跃供应商,并使用其评论的平均评分进行注释。您确定审核是供应商审核而非产品审核的方式是产品字段为空。并且您希望没有评论的供应商的平均评分为零。

在SQL中,您的查询需要OUTER JOIN

SELECT vendor.id, COALESCE(AVG(review.rating), 0.0) AS rating
  FROM myapp_vendor AS vendor
  LEFT OUTER JOIN myapp_review AS review
    ON review.vendor_id = vendor.id
       AND review.product IS NULL
  WHERE vendor.category = %s
    AND vendor.active
  GROUP BY vendor.id

有时在Django中,最简单的解决方案是raw SQL query:正如开发人员所说,数据库API是“a shortcut but not necessarily an end-all-be-all.”所以看起来像这样:

for v in Vendor.objects.raw('SELECT ... ', [category]): # query as above
    print 'Vendor {0} has rating {1}'.format(v.name, v.rating)

答案 1 :(得分:0)

好的,我可能在这里错了。我做了一个小测试,它给了我正确的结果,但我不得不花更多的时间测试,我现在没有。

你可以试试这个:

vendor_list = Vendor.objects.filter(category=category, active=True)
vendor_list = vendor_list.filter(Q(review__product__isnull=True)|Q(review__isnull=True)).annotate(rating_avg=Avg('review__rating'))

(过滤器已分为2行,以便于阅读,但可以合并)

这个想法是你首先接受所有供应商,然后筛选那些没有产品评论或根本没有评论的人。然后你注释那些。

缺少审核的供应商的评级为“无”而非“0”。