Поля доступа в промежуточной модели Django

Я создаю группу Person и членство, как описано в документах Django для промежуточной модели.

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)

Доступ к объекту Person из объекта Group возможен с помощью:

>>>Group.members.name

Создает ли Django другой запрос для извлечения Person? Могу ли я получить доступ к полю date_joined из объекта Group?

То, что меня смущает, это то, что я ожидаю получить поле "Имя пользователя" с помощью:

>>>Group.members.person.name

Что произойдет, если у Человека есть поле "имя", а также промежуточная модель имеет поле "имя".

Ответы

Ответ 1

Поле членов в вашем примере - это ManyToManyField, поэтому это способ доступа ко многим людям, а не к одному человеку. Объект, находящийся под полем членов, фактически является особым типом Менеджера, а не Person:

>>>print my_group.members
<django.db.models.fields.related.ManyRelatedManager object at 0x181f7d0>

Чтобы лучше понять, что такое менеджер, см. документацию.

Чтобы получить доступ к имени пользователя, вы должны сделать, например:

>>>for person in my_group.members.all():
>>>    print person.name

Вы не можете получить доступ к полям в своей модели членства через Менеджер в поле "Члены". Чтобы получить доступ к любому из полей в нем, вы должны:

>>>for membership in my_group.membership_set.all():
>>>    print membership.date_joined

Итак, если у вас есть поле с именем name в вашей модели членства, вы получите доступ к нему следующим образом:

>>>for membership in my_group.membership_set.all():
>>>    print membership.name

Второй способ доступа к имени Person:

>>>for membership in my_group.membership_set.all():
>>>    print membership.person.name

Надеюсь, что это поможет немного:)

Ответ 2

Используйте менеджер класса членства:

MyGroup.membership_set.all()

вместо:

MyGroup.members.all()