Django join по полю, которое не является ForeignKey
Я новичок в Django, но я делаю игру, одним из элементов которой является голосование игроков друг за друга.
Вот модели, которые я установил (только соответствующие поля)
#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)
Когда пользователь присоединяется к игре, он получает запись в модели "Player", а когда он отдает голос за другого игрока, в модель "PlayerVote" добавляется запись, показывающая, какой игрок проголосовал (byplayer) и за кого он проголосовал (forplayer).
Я хотел бы создать QuerySet, содержащий каждого игрока и количество полученных им голосов.
Я пробовал использовать annotate, который, кажется, может дать мне подсчет количества голосов, но он по умолчанию присоединяется к полю byplayer, поэтому в итоге я получаю количество голосов, отданных каждым игроком, а не количество голосов, полученных каждым игроком.
В SQL я бы просто сделал join на Player.pk = PlayerVote.forplayer.pk, можно ли сделать что-то подобное в Django?
Как вариант, я мог бы создать дополнительную модель, которая суммирует голоса, полученные каждым игроком, и увеличивает их на 1 за каждый отданный голос, но это кажется излишним
Вы можете .annotate(…)
[Django-doc] с:
from django.db.models import Count
Player.objects.annotate(score=Count('voteforplayer'))
Объекты Player
, возникающие из этого QuerySet
, будут иметь дополнительный атрибут .score
, содержащий количество PlayerVote
, но с forplayer_id
вместо него.