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 вместо него.

Вернуться на верх