В Django, как вы извлекаете данные из дополнительных полей для отношений «многие ко многим» без явного запроса? - PullRequest
15 голосов
/ 29 января 2009

Учитывая ситуацию в 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()

Отношение «многие ко многим» позволяет получить доступ к связанным данным, используя атрибуты (атрибут «Players» в объекте Team или используя атрибут «groups» в объекте «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 Ответ

9 голосов
/ 30 января 2009

Итак, через 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

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

...