Как получить доступ к свойствам таблицы "через" многих из многих из шаблона django?
Из документации Django...
Когда вы имеете дело с простыми отношениями "многие ко многим" , такими как смешивание и сопоставление пиццы и начинки, вам нужен стандартный многопользовательский многопользовательский режим. Однако иногда вам может потребоваться связать данные с отношением между двумя моделями.
Например, рассмотрим случай приложения, отслеживающего музыкальные группы, к которым принадлежат музыканты. Между человеком и группами, членами которых они являются, существует взаимосвязь "многие-ко-многим", поэтому вы можете использовать ManyToManyField для представления этих отношений. Тем не менее, есть много подробностей о членстве, которое вы, возможно, захотите собрать, например, о дате, когда человек присоединился к группе.
В этих ситуациях Django позволяет указать модель, которая будет использоваться для управления отношениями "многие ко многим" . Затем вы можете поместить дополнительные поля в промежуточную модель. Промежуточная модель связана с ManyToManyField, используя сквозной аргумент, чтобы указать на модель, которая будет действовать как посредник. Для нашего примера музыканта код выглядел бы примерно так:
class Person(models.Model):
name = models.CharField(max_length=128)
def __unicode__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
def __unicode__(self):
return self.name
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
Теперь, когда вы настроили свой ManyToManyField для использования вашей модели-посредника (в этом случае членство), вы готовы начать создавать отношения "многие ко многим" . Вы делаете это, создавая экземпляры промежуточной модели:
ringo = Person.objects.create(name="Ringo Starr")
paul = Person.objects.create(name="Paul McCartney")
beatles = Group.objects.create(name="The Beatles")
m1 = Membership(person=ringo, group=beatles,
... date_joined=date(1962, 8, 16),
... invite_reason= "Needed a new drummer.")
m1.save()
beatles.members.all()
[<Person: Ringo Starr>]
ringo.group_set.all()
[<Group: The Beatles>]
m2 = Membership.objects.create(person=paul, group=beatles,
... date_joined=date(1960, 8, 1),
... invite_reason= "Wanted to form a band.")
beatles.members.all()
[<Person: Ringo Starr>, <Person: Paul McCartney>]
источник: http://docs.djangoproject.com/en/dev/topics/db/models/#intermediary-manytomany
Мой вопрос в том, как настроить мой просмотр и шаблон для доступа к этим дополнительным атрибутам. Скажем, у меня есть страница группы, и я хочу отобразить название группы, перебрать записи членства и отобразить имена и дату_соединения.
Должен ли я передать объект группы в шаблон? Или я каким-то образом передаю объекты членства?
И как мне создать петли for внутри шаблона?
Спасибо.
Ответы
Ответ 1
Самый простой способ - просто передать группу в шаблон. Шаблоны способны переходить к отношениям между моделями, и на группе есть как члены, так и члены_setsetsetsetset. Итак, вот как я это сделаю:
Вид:
def group_details(request, group_id):
group = get_object_or_404(Group, pk=group_id)
return render_to_response('group_details.html',
{'group': group})
шаблон:
<h2>{{ group.name }}</h2>
{% for membership in group.membership_set.all %}
<h3>{{ membership.person }}</h3>
{{ membership.date_joined }}
{% endfor %}
Ответ 2
Я не уверен, что это только решение или нет, но передача объектов отношения к шаблону, безусловно, работает. На ваш взгляд, получите объекты QuerySet of Membership:
rel = Membership.objects.filter( group = your_group ).select_related()
и передать его в шаблон, где вы можете перебирать его с помощью {% for %}
{% for r in rel %}
{{ r.person.name }} joined group {{ r.group.name }} on {{ r.date_joined }}<br />
{% endfor %}
Обратите внимание, что это не должно выполнять никаких дополнительных запросов из-за select_related()
.