如何使用Django查询集编写此原始SQL查询?

时间:2019-01-08 07:38:10

标签: django django-queryset

我在不同的应用程序中有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进行分组的原因是,许多用户可以对一本书进行评分。

1 个答案:

答案 0 :(得分:1)

请尝试向查询中添加distinct=True并删除values(),最好调用Book模型注释。

Book.objects.annotate(rating_avg=Avg('bookratings__rating', distinct=True)).order_by('-rating_avg')

类似的情况,但是在Count中,您可以在Django docs中找到。