我正在编写一个联盟系统,我希望在每个赛季中显示每个球员在该赛季累积的积分排名。
到目前为止,我设法使用与此类似的代码:
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()。
答案 0 :(得分:0)
这会返回可用的结果:
Season.objects.values('name','match__matchresult__player__username').annotate(points=Sum('match__matchresult__points')).distinct()
我还需要实现SumWithDefault来摆脱NULL:
from django.db.models.sql.aggregates import Aggregate
from django.db.models import Aggregate as Ag
class SumWithDefaultSQL(Aggregate):
def __init__(self, col, default=None, **extra):
super(SumWithDefaultSQL, self).__init__(col, default=default, **extra)
self.sql_function = 'SUM'
if default is not None:
self.sql_template = 'COALESCE(%(function)s(%(field)s), %(default)s)'
class SumWithDefault(Ag):
name = 'Sum'
def add_to_query(self, query, alias, col, source, is_summary):
aggregate = SumWithDefaultSQL(col, source=source, is_summary=is_summary, **self.extra)
query.aggregates[alias] = aggregate
最终查询:
Season.objects.values('name','match__matchresult__player__username').annotate(points=SumWithDefault('match__matchresult__points', default=0)).distinct().order_by('-points')
答案 1 :(得分:-1)
Django的ORM并未涵盖所有用例。
您可以将聚合存储在单独的模型中,也可以回退到原始SQL。