Django ORM:根据相关的模型计数创建排名

问题描述 投票:1回答:1

我的数据库中有2个模型:MovieComment(它有一个指向Movie的外键)。

from django.db import models


class Movie(models.Model):
    title = models.CharField(max_length=120, blank=False, unique=True)

class Comment(models.Model):
    movie = models.ForeignKey(movie_models.Movie, null=False, on_delete=models.CASCADE)
    body = models.TextField(blank=True)

我想要做的是创建Movies的排名,其中位置由相关的Comments的数量决定。

我可以注释注释的数量并正确地排序结果:

from django.db.models import Count

qs = Movie.objects.annotate(total_comments=Count('comment')).order_by('-total_comments')

这给了我正确顺序的查询集,但我想再做一件事 - 为每一行注释'rank'。

所以我的问题是:如何对结果的每一行添加“排名”?请注意,具有相同评论数量的电影需要具有相同的等级。

|  movie_title | total_comments | rank |
|--------------|----------------|------|
| mov1         | 10             | 1    |
| mov2         | 5              | 2    |
| mov3         | 5              | 2    |
| mov4         | 3              | 3    |

我试图使用window functions,因为一些例子对我来说似乎合法:

from django.db.models import F, Window

dense_rank = Window(
    expression=DenseRank(),
    order_by=F('total_comments').desc()
)

qs = Movie.objects.annotate(total_comments=Count('comment')).annotate(rank=dense_rank)

但运行此查询会引发django.db.utils.OperationalError: near "(": syntax error

django django-models django-2.0
1个回答
2
投票

如果查询得到适当的排序,RowNumber应该足够了:

from django.db.models import Count
from django.db.models.expressions import F, Window
from django.db.models.functions.window import RowNumber

qs = (Movie.objects
    .annotate(total_comments=Count('comment'))
    .order_by('total_comments')
    .annotate(rank = Window(expression=RowNumber())
)

但由于行号是记录序列中固有的,所以Kevin正确地提出了一种简单的Python方法(例如enumerate),因为无论如何你将在某个时刻迭代记录集。

如果您希望记录集的排序与排名不同,则会有所不同,那么将Window与单独的order_by参数一起使用是有意义的。

我不确定所有后端是否支持RowNumber

© www.soinside.com 2019 - 2024. All rights reserved.