В Django, как вы извлекаете данные из дополнительных полей для отношений "многие ко многим" без явного запроса?

Учитывая ситуацию в Django 1.0, где у вас есть дополнительные данные по отношениям "многие-ко-многим" :

class Player(models.Model):
  name = models.CharField(max_length=80)

class Team(models.Model):
  name = models.CharField(max_length=40)
  players = models.ManyToManyField(Player, through='TeamPlayer', related_name='teams')

class TeamPlayer(models.Model):
  player = models.ForeignKey(Player)
  team = models.ForeignKey(Team)
  captain = models.BooleanField()

Отношение "многие ко многим" позволяет вам получить доступ к связанным данным с помощью атрибутов (атрибут "игроки" в объекте "Команда" или использовать атрибут "команды" на объекте Player посредством связанного с ним имени). Когда один из объектов помещается в контекст для шаблона (например, команда, помещенная в контекст для визуализации шаблона, который генерирует список команд), к связанным объектам можно получить доступ (т.е. к игрокам в командах), но как можно можно получить дополнительные данные (например, "капитан" ) вместе с связанными объектами из объекта в контексте (например, с командой) без добавления дополнительных данных в контекст?

Я знаю, что можно получить прямой запрос к таблице промежуточных элементов, чтобы получить дополнительные данные. Например:

TeamPlayer.objects.get(player=790, team=168).captain

Или:

for x in TeamPlayer.objects.filter(team=168):
  if x.captain:
    print "%s (Captain)" % (x.player.name)
  else:
    print x.player.name

Выполняя это непосредственно в таблице промежуточных элементов, мне требуется разместить дополнительные данные в контексте шаблона (результат запроса на TeamPlayer), который я пытаюсь избежать, если такая возможность возможна.

Ответы

Ответ 1

Итак, через 15 минут после вопроса, и я нашел свой собственный ответ.

Используя dir(Team), я вижу другой сгенерированный атрибут с именем teamplayer_set (он также существует в Player).

t = Team.objects.get(pk=168)
for x in t.teamplayer_set.all():
  if x.captain:
    print "%s (Captain)" % (x.player.name)
  else:
    print x.player.name

Не знаю, как я настроил бы это сгенерированное имя_соединения, но, по крайней мере, я знаю, что могу получить данные из шаблона без добавления дополнительных результатов запроса в контекст.