我正在尝试创建一个排行榜,我试图确定一个最佳的结构来避免出现问题。
目前,我有三个模型代表我要收集的数据。 Season
,Challenge
,Attempt
。
class Season(models.Model):
season = models.CharField(max_length=4)
start_date = models.DateTimeField()
end_date = models.DateTimeField()
class Challenge(models.Model):
season = models.ForeignKey(Season, on_delete=models.CASCADE)
name = models.CharField(max_length=255)
start_date = models.DateTimeField()
end_date = models.DateTimeField()
class Attempt(models.Model):
challenger = models.ForeignKey(User, on_delete=models.CASCADE)
challenge = models.ForeignKey(Challenge, on_delete=models.CASCADE)
points = models.IntegerField(default=0)
现在,我想从我希望得到的内容中得出以下结论。
我尝试显示数据时会遇到困难。我想返回当前赛季的排行榜,该排行榜计算出每个挑战用户的最佳尝试,并返回一个包含该用户及其整个赛季总积分的查询集。
示例数据
Season(season='2019',
start_date=..., # some date object
end_date=..., # some date object
)
Challenge(season=1, # represents season object above
name='Challenge 1',
start_date=..., # some date object
end_date=..., # some date object
)
Challenge(season=1, # represents season object above
name='Challenge 2',
start_date=..., # some date object
end_date=... # some date object
)
Attempt(challenger=1, # represents user object
challenge=1, # represents challenge 1 above
points=5
)
Attempt(challenger=2, # represents user object
challenge=1, # represents challenge 1 above
points=10
)
Attempt(challenger=1, # represents user object
challenge=2, # represents challenge 2 above
points=5
)
Attempt(challenger=2, # represents user object
challenge=2, # represents challenge 2 above
points=10
)
预期结果
如何使该模型更好地表示我需要的结果。我已经看过直通关系,但不确定是否完全了解或在这里是否需要。
然后我将如何使用ORM获得所需的结果
答案 0 :(得分:1)
您的模型很好,请不要更改。为获得所需的结果,请尝试如下操作:
Attempt.objects.filter(challenge__season__season='2019').values('challenger__name').annotate(total_points=Sum('points')).order_by('-total_points')
这将进行所有尝试,将其过滤为名称为'2019'的季节,然后获取所有挑战者名称,然后将其汇总为挑战者尝试点的总和(这似乎是您想要的,但是您也可以使用“ Max”代替“ Sum”。
这种方法的一个问题(顺便说一句,我必须归功于此消息来源:https://simpleisbetterthancomplex.com/tutorial/2016/12/06/how-to-create-group-by-queries.html)是,如果多个挑战者具有相同的名称,他们将被分组在一起,这可能是您不想要的。因此,您可能希望改为按挑战者“ pk”和“名称”分组。