【问题标题】:Aggregate for multiple instances with a ManyToOne relation聚合具有多对一关系的多个实例
【发布时间】:2021-11-06 11:29:14
【问题描述】:

我是 Django 新手,我想建立一个网站来跟踪棋盘游戏。

我想要什么:对于每一轮比赛,玩家都会获得积分,我想创建一个表格来显示每个玩家所有得分的总和。

我的模型如下:

class Player(models.Model):
    name = models.CharField(max_length=150)

class Score(models.Model):
    player = models.ForeignKey(Player, blank=False, null=False, on_delete=models.PROTECT)
    scorevalue = models.IntegerField(blank=False, null=False)

我想获得一个包含所有玩家的查询集,其中添加了一个包含他的分数总和的附加字段。在 SQL 中类似

Select distinct playername, sum(scorevalue) over (partition by playername) 
from Players 
Join Scores

我的主要问题是结合实例和查询集来理解“聚合”和“注释”函数之间的联系。

有一个实例我可以得到

Player.objects.get(pk=1).score_set.aggregate(score_sum=Sum('scorevalue'))

但是是否可以对查询集中的每个实例都执行此操作?

感谢您的帮助。

【问题讨论】:

    标签: python django


    【解决方案1】:

    是的,在这种情况下,您注释对象,因此:

    from django.db.models import Sum
    
    Player.objects.annotate(
        score_sum=Sum('score__scorevalue')
    )

    由此查询集产生的Player 对象将有一个额外的属性.score_sum,它是相关Score 记录的总和。

    可以利用两个连续的下划线 (__) 来“透视”关系,从而访问相关模型记录的数据。

    【讨论】:

    • 谢谢,效果很好。所以连接是在 Sum 中声明的,我总是先尝试这样做,然后在查询集上进行注释。是否可以根据 Score 具有的其他外键进行进一步过滤,例如 Round 是否是与 Score 连接的单独实体?
    • @thream:您可以使用Prefetch object 来做到这一点,但我建议您提出一个新问题,并分享相关模型。
    • sum 中的过滤器完成了这项工作:Player.objects.annotate(sum_scorevalue=Coalesce(Sum('score__scorevalue', filter=Q(score__round__somebooleanfield=True)), 0))
    • @thream: 唯一可能出现的问题是,如果Score 可以有多个 rounds,那么它将多次计算该分数因为有rounds 和somebooleanfield=True。
    猜你喜欢
    • 2020-09-03
    • 2020-09-02
    • 1970-01-01
    • 2016-01-13
    • 1970-01-01
    • 1970-01-01
    • 2017-09-11
    • 1970-01-01
    • 2020-07-27
    相关资源
    最近更新 更多