Django查询中values()方法后的计数和最大值

1 投票
2 回答
3867 浏览
提问于 2025-04-18 04:08

我有一个Django模型:

class Action(models.Model):
    id = models.AutoField(primary_key=True)
    game = models.ForeignKey(Game)
    step = models.ForeignKey(Step)
    from_player = models.ForeignKey(Player)
    to_player = models.ForeignKey(Player)
    type = models.ForeignKey(ActionType)
    timestamp = models.DateTimeField(default=timezone.now)

我想做以下几件事:

  1. 根据游戏、步骤和类型进行筛选
  2. 找出获得最多操作次数的玩家

为此,我尝试了:

v = Action.objects.filter(game=1, step=2)
v = v.filter(type=3)
v = v.values('to_player').order_by().annotate(count=Count('to_player'))
v = v.annotate(max=Max('count')).filter(count=F('max')) #try to select the max

但是最后一行给我报错(因为第三行返回的是一个字典列表):

Cannot compute Max('count'): 'count' is an aggregate

我知道可能已经有人回答过类似的问题,但Django的values()和aggregate()对我来说有点复杂。我该怎么做才对呢?

2 个回答

0

这个错误给了我们一个提示,你应该用aggregate而不是annotate来获取最大值:

v = Action.objects.filter(game=1, step=2)
v = v.filter(type=3)
v = v.values('to_player').order_by().annotate(count=Count('to_player'))
v = v.aggregate(max=Max('count')).filter(count=F('max')) #try to select the max

我不确定最后的过滤器是否有效,但试试看也没坏处。

3

你可以使用Django的.latest()方法来获取最高的计数。虽然这个方法主要是为日期设计的,但它也可以用在字符串和整数上。

这样你就能找到那个对玩家数量最高的动作:

# combined the filters, no need to separate into two steps
v = Action.objects.filter(game=1, step=2, type=3)
v = v.annotate(count=Count('to_player'))
v = v.latest('count') # will return Action with the highest count

撰写回答