私はリーグシステムを書いていて、そのシーズン中に各プレイヤーが獲得したポイントでソートされた各シーズンのプレイヤーランキングを表示したいと考えています。
これまでのところ、次のようなコードでそれを行うことができました:
class Player(models.Model):
name = models.CharField(max_length=100)
class Season(models.Model):
name = models.CharField(max_length=100)
start_date = models.DateField()
end_date = models.DateField()
players = models.ManyToManyField(Player)
def get_player_rank(self, player):
return player.matchresult_set.filter(season=self).aggregate(points=Sum('points'))['points']
def get_ranks(self):
ranks = [(player, self.get_player_rank(player)) for player in self.players.all()]
ranks.sort(key=lambda tup: tup[1])
return ranks
class Match(models.Model):
date = models.DateField()
players = models.ManyToManyField(Player, through='MatchResult')
season = models.ForeignKey(Season)
class MatchResult(models.Model):
player = models.ForeignKey(Player)
match = models.ForeignKey(Match)
points = models.IntegerField()
もっと単純な集計でも同じことができると思いますが、 annotate() を正しく取得できません。
これを試してみましたが、シーズン全体のすべてのポイントを合計しただけです。
class Season(models.Model):
def get_ranks(self):
return self.players.annotate(points=Sum('matchresult__points')).order_by('-points')
私は何が欠けていますか?移植可能なコードになる場合は、 .extra() を使用できると思います。