如何使用 Django 模型向已注释的查询集添加第二个注释

时间:2021-03-26 15:15:52

标签: python django

我想创建一个包含以下列的查询集

电影.id |电影.title |电影.description |电影.maximum_rating |电影.maximum_rating_user

以下是我的模型和我尝试过的代码。

models.py

from django.contrib.auth.models import AbstractUser
from django.db import models

class User(AbstractUser):
    pass
    
class Rating(models.Model):
    movie = models.ForeignKey(Movie, on_delete=models.CASCADE, related_name="ratings")
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="ratings")
    score = models.DecimalField(decimal_places=2, max_digits=9)
    
class Movie(models.Model):
    title = models.CharField(max_length=64)
    description = models.TextField(max_length=4096)

当我运行下面的代码时,控制台会打印以下内容: (基本上这显示了实验数据库中的所有数据)

views.py

def index(request, movie_id):
    movies = Movie.objects.all().annotate(
            maximum_rating=Max('ratings__score'), 
            maximum_rating_user=F('ratings__user')
            )
    for movie in movies:
        print(movie.id, movie.title, movie.description, movie.maximum_rating, movie.maximum_rating_user)
    return HttpResponse("")
<头>
id 标题 描述 评分 用户
1 跳猫 狂奔 2 1
1 跳猫 狂奔 1 2
1 跳猫 狂奔 5 3
1 跳猫 狂奔 4 4
2 终结者 我会回来的! 8 1
2 终结者 我会回来的! 6 2
2 终结者 我会回来的! 4 3
2 终结者 我会回来的! 10 4
3 小飞象 华特迪士尼 6 1
3 小飞象 华特迪士尼 8 2
3 小飞象 华特迪士尼 9 3
3 小飞象 华特迪士尼 2 4
4 细红线 战时 9 1
4 细红线 战时 2 2
4 细红线 战时 5 3
4 细红线 战时 8 4

现在我想修改查询,以便它只返回评分具有最大值的每部电影的行。

当我删除第二个注释时,查询会为每部电影返回一行且评分最高,但用户没有被注释。

views.py

def index(request, movie_id):
    movies = Movie.objects.all().annotate(
            maximum_rating=Max('ratings__score'))
    for movie in movies:
        print(movie.id, movie.title, movie.description, movie.maximum_rating)
    return HttpResponse("")
<头>
id 标题 描述 评分
1 跳猫 狂奔 5
2 终结者 我会回来的! 10
3 小飞象 华特迪士尼 9
4 细红线 战时 9

我应该如何修改查询以使其返回 abave 查询集但注释发布最高评分的用户?

1 个答案:

答案 0 :(得分:1)

您可以使用 Subquery expression [Django-odc] 来确定评价最高的用户:

from django.db.models import OuterRef, Subquery

def index(request, movie_id):
    movies = Movie.objects.all().annotate(
        maximum_rating=Max('ratings__score'),
        max_user=Subquery(
            Rating.objects.filter(
                movie=OuterRef('pk')
            ).order_by('-score').values('user')[:1]
        )
    )
    for movie in movies:
        print(movie.id, movie.title, movie.description, movie.maximum_rating)
    return HttpResponse("")
相关问题