[英]Django filter with annotate
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”,..該怎么辦?
讓我們看看我是否理解這一點。 您試圖列出該類別中所有活躍的供應商,並注明其評論的平均評分。 您確定評論是供應商評論而不是產品評論的方式是產品字段為空。 您希望沒有評論的供應商的平均評分為零。
在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中,最簡單的解決方案是原始SQL查詢 :如開發人員所說,數據庫API是“ 快捷方式,但不一定是萬事俱備。 ”因此,看起來像這樣:
for v in Vendor.objects.raw('SELECT ... ', [category]): # query as above
print 'Vendor {0} has rating {1}'.format(v.name, v.rating)
好吧,我在這里可能是錯的。 我做了一個小測試,它給了我正確的結果,但是我將不得不花費更多的時間進行測試,而我現在還沒有。
您可以嘗試以下方法:
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'))
(過濾器分為兩行,以便於閱讀,但可以合並)
這樣的想法是,您首先選擇所有供應商,然后過濾那些沒有產品評論或完全沒有評論的供應商。 然后,您對它們進行注釋。
對於那些未通過審核的供應商,其評分為“無”而不是0。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.