我在不同的应用程序中有2种型号:
app1 / model.py
class BookRatings(models.Model):
book = models.ForeignKey('app2.Book', on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE, default=User)
rating = models.PositiveSmallIntegerField(default=0, help_text='Book Rating out of 10')
app2 / model.py
class Book(models.Model):
title = models.CharField(max_length=250, unique=True)
slug = models.SlugField(max_length=50)
description = models.TextField(max_length=500)
我想以降序顺序获得每本书的平均评分以及这本书的所有详细信息,并且还能够访问Book模型中的方法,例如get_absolute_url(),因此我首先尝试使用以下代码
BookRatings.objects.values('book').annotate(rating_avg=Avg('rating')).order_by('-rating_avg')
这确实为我提供了正确的值(书ID和rating_avg),但是不可能获得外键模型书的所有字段。像书名或说明一样。
我搜索了一下,发现可以在值中添加更多列,就像
BookRatings.objects.values('book','book__title','book__description').annotate(rating_avg=Avg('rating')).order_by('-rating_avg')
。
但是,这仍然不允许我访问书籍模型中的方法,例如get_absolute_url
。我尝试了book__get_absolute_url
的值,但出现错误,它不是书本领域。
由于我已经直接了解SQL,所以我成功创建了一个原始sql语句,该语句可以获取所需的所有内容。
Book.objects.raw('select rb.*,(select avg(rating) from app1_bookratings as ab where ab.book_id=rb.id group by ab.book_id) as rating_avg from app2_book as rb order by rating_avg desc')
这确实为我提供了我需要的所有值,并且我什至能够访问get_absolute_url
,因为即时通讯使用Book.objects
,但我仍然认为如果我学会了一种实现方法会更好这使用Django的查询集。
顺便说一句,我在BookRatings中对book
进行分组的原因是,许多用户可以对一本书进行评分。
答案 0 :(得分:1)
请尝试向查询中添加distinct=True
并删除values()
,最好调用Book
模型注释。
Book.objects.annotate(rating_avg=Avg('bookratings__rating', distinct=True)).order_by('-rating_avg')
类似的情况,但是在Count
中,您可以在Django docs中找到。