这是上一个问题的后续问题,但我将在此处包含所有详细信息。
我正在创建一款游戏,其中一个要素是玩家互相投票。
这是我设置的模型(仅限相关字段)
我的
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')
尝试这个查询:
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}]>