如何在Django中实现Annotate和Filter

问题描述 投票:0回答:1

这是上一个问题的后续问题,但我将在此处包含所有详细信息。

我正在创建一款游戏,其中一个要素是玩家互相投票。

这是我设置的模型(仅限相关字段)

我的

models.py

class Game(models.Model):
  gamecode = ShortUUIDField(length=4, max_length=4, unique=True)
  phasenumber = models.IntegerField(default=1)
  isActive = models.BooleanField(default=True)

class Player(models.Model):
  game = models.ForeignKey(Game, on_delete=models.CASCADE)
  user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
  isPlaying = models.BooleanField(default=True)

class PlayerVote(models.Model):
  byplayer = models.ForeignKey(Player, on_delete=models.CASCADE)
  forplayer = models.ForeignKey(Player, on_delete=models.CASCADE, related_name="voteforplayer")
  gamephasenumber = models.IntegerField()
  timestamp = models.DateTimeField(auto_now_add=True)

当用户加入游戏时,他们会在“玩家”模型中获得一个条目。当他们为另一个玩家投票时,“PlayerVote”模型中会添加一个条目,显示哪个玩家投票(byplayer)、他们投票给谁(forplayer)以及游戏所处的阶段(gamephasenumber)(这只是增加游戏每个阶段的整数)

我想做的是创建一个查询集,其中包含每个玩家以及他们在游戏的这个阶段获得了多少票。

我可以执行以下操作来获取他们在所有阶段收到的选票

playerswithvotes = Player.objects.select_related('game').filter(game = activegame.game, game__phasenumber = activegame.game.phasenumber, isPlaying = True).annotate(votesreceived=Count('voteforplayer')).order_by('-votesreceived')

但是我怎样才能只显示他们在这个阶段收到的选票数呢?

我已尝试过以下各项:

votesthisround = Count("playervote", filter=Q(playervote__gamephasenumber = activegame.game.phasenumber))
playerswithvotes = Player.objects.select_related('game').filter(game = activegame.game, game__phasenumber = activegame.game.phasenumber, isPlaying = True).annotate(votesreceived=votesthisround).order_by('-votesreceived')
playerswithvotes = Player.objects.select_related('game').filter(game = activegame.game, game__phasenumber = activegame.game.phasenumber, isPlaying = True).annotate(votesreceived=Count('voteforplayer', filter=Q(playervote__gamephasenumber = activegame.game.phasenumber))).order_by('-votesreceived')
playerswithvotes = Player.objects.select_related('game').filter(game = activegame.game, game__phasenumber = activegame.game.phasenumber, isPlaying = True).annotate(votesreceived=Count('voteforplayer')).filter(playervote__gamephasenumber = activegame.game.phasenumber).order_by('-votesreceived')
python django django-models django-queryset django-annotate
1个回答
0
投票

尝试这个查询:

PlayerVote.objects.filter(forplayer__game=activegame.game, gamephasenumber=activegame.game.phasenumber).values("forplayer").annotate(votes=Count("pk"))

使用

.values()
让我们可以在 Django 生成的 SQL 查询中使用
GROUP BY
,这样我们就可以根据 PlayerVotes 的接收者对输出进行分组。结果如下:
<QuerySet [{'forplayer': 1, 'votes': 1}, {'forplayer': 3, 'votes': 2}]>

如果您想要了解每轮中哪些玩家获得了投票的摘要,您可以从过滤器中删除游戏阶段并将其添加到查询的

.values()
部分:

PlayerVote.objects.filter(forplayer__game=activegame.game).values("forplayer", "gamephasenumber").annotate(votes=Count("pk"))

输出如下:

<QuerySet [{'forplayer': 1, 'gamephasenumber': 1, 'votes': 1}, {'forplayer': 2, 'gamephasenumber': 2, 'votes': 2}, {'forplayer': 3, 'gamephasenumber': 1, 'votes': 2}, {'forplayer': 3, 'gamephasenumber': 2, 'votes': 1}]>

© www.soinside.com 2019 - 2024. All rights reserved.