@ Лазерная наука абсолютно верна. Вы должны настроить свои модели, поскольку вы устанавливаете фактические отношения «многие ко многим»; это позволит вам использовать больше возможностей интерфейса администратора и т. д.
Кроме того, независимо от того, нет необходимости переходить на raw()
, поскольку это можно сделать полностью с помощью обычного использования Django ORM.
Что-то вроде:
class LadderPlayer(models.Model):
player = models.ForeignKey(User, unique=True)
position = models.IntegerField(unique=True)
challenges = models.ManyToManyField("self", symmetrical=False, through='Match')
class Match(models.Model):
date = models.DateTimeField()
challenger = models.ForeignKey(LadderPlayer)
challengee = models.ForeignKey(LadderPlayer)
должно быть все, что вам нужно изменить в моделях. После этого вы сможете выполнить запрос типа
player_of_interest = LadderPlayer.objects.filter(pk=some_id)
matches_of_interest = \
Match.objects.filter(Q(challenger__pk=some_id)|Q(challengee__pk=some_id))
, чтобы получить всю интересующую информацию о данном игроке. Обратите внимание, что для этого вам понадобится from django.db.models import Q
.
Если вы хотите точно ту же информацию, которую вы предоставляете в своем примере запроса, я считаю, что было бы проще разделить запросы на отдельные для получения списков претендентов и претендентов - например, что-то вроде:
challengers = LadderPlayer.objects.filter(challenges__challengee__pk=poi_id)
challenged_by = LadderPlayer.objects.filter(challenges__challenger__pk=poi_id)
получит два соответствующих набора запросов для интересующего игрока (с первичным ключом poi_id
).
Если есть какая-то конкретная причина, по которой вы не хотите, чтобы фактические отношения «многие ко многим» стали де-юре, вы можете изменить их на что-то вроде
challenger = LadderPlayer.objects.filter(match__challengee__pk=poi_id)
challenged_by = LadderPlayer.objects.filter(match__challenger_pk=poi_id)
Таким образом, предложение для изменения модели состоит просто в том, чтобы помочь использовать существующие инструменты и сделать явным отношение, которое у вас в настоящее время происходит неявно.
В зависимости от того, как вы хотите его использовать, вы можете сделать что-то вроде
pl_tuple = ()
for p in LadderPlayer.objects.all():
challengers = LadderPlayer.objects.filter(challenges__challengee__pk=p.id)
challenged_by = LadderPlayer.objects.filter(challenges__challenger__pk=p.id)
pl_tuple += (p.id, p.position, challengers, challenged_by)
context_dict['ladder_players'] = pl_tuple
по вашему мнению, чтобы подготовить данные для вашего шаблона.
В любом случае, вы, вероятно, должны выполнять запрос через ORM Django, вместо использования raw()
в этом случае.