首页 > 解决方案 > Django:从相关对象注释排名

问题描述

型号:

class Competition(TimeStampedModel):
    name = models.CharField(max_length=255)

class Playlist(TimeStampedModel):
    competition = models.OneToOneField(Competition, on_delete=models.CASCADE, related_name='playlist')

class Entry(TimeStampedModel):
    title = models.CharField(max_length=255)
    by = models.CharField(max_length=255)

class Vote(TimeStampedModel):
    entry = models.ForeignKey(Entry, on_delete=models.CASCADE, related_name="votes")
    score = models.IntegerField(validators=[validate_vote_value])

class PlaylistEntry(TimeStampedModel):
    playlist = models.ForeignKey(Playlist, on_delete=models.CASCADE, related_name='entries')
    entry = models.ForeignKey(Entry, on_delete=models.CASCADE, related_name='playlistentries')

一场比赛有一个播放列表。一个竞赛播放列表有许多 PlaylistEntry。PlaylistEntry 是一个条目。一个条目可以有多个投票。

我能够实现的目标:计票。我需要实现的目标:每个播放列表的排名。

我现在使用的代码:

def get_context_data(self, **kwargs):
    ctx = super().get_context_data(**kwargs)
    ctx["compos"] = Playlist.objects \
        .filter(competition__hidden_in_results=False) \
        .prefetch_related(
        Prefetch(
            "entries",
            PlaylistEntry.objects
                .select_related("entry")
                .annotate(score=Sum("entry__votes__score"))
                .annotate(rank=Window(expression=Rank(), order_by=F('score').desc()))
                .annotate(overall_rank=Window(expression=Rank(), order_by=F('score').desc()))
                .all(),
            to_attr="compo_entries"
        )) \
        .select_related("competition") \
        .order_by("competition__results_play_order")
    return ctx

这给了我想要的每个条目的投票总和。它还给了我在所有 PlayList 中的总排名。我需要每个播放列表的排名

电流输出:

Playlist Item 1     Rank    Overall     Score   
entry               113.    113.        196     
entry               124.    124.        178     
Playlist Item 2     Rank    Overall     Score   
entry               56.     56.         336     
entry               62.     62.         323     

我想要什么:

Playlist Item 1     Rank    Overall     Score   
entry               1.      113.        196     
entry               2.      124.        178     
Playlist Item 2     Rank    Overall     Score   
entry               1.      56.         336     
entry               2.      62.         323 

标签: djangoormrelational-database

解决方案


答案是在组合中添加partition_by关键字:

.annotate(rank=Window(expression=Rank(), partition_by=[F('playlist')], order_by=F('score').desc()))

非常感谢 irc 中的 FunkyBob


推荐阅读