как вернуть все поля записи в отношениях «многие ко многим»

#django

#django

Вопрос:

У меня есть эти таблицы:

 class Contract(models.Model):
    project = models.ForeignKey(Project)
    start_date = models.DateField()
    agreed_contacts = models.ManyToManyField(Contact, through='ContractPartyInvolved')


class ContractPartyInvolved(models.Model):
    contact = models.ForeignKey(Contact)
    contract = models.ForeignKey(Contract)
    role = models.ForeignKey(Role)
    agreed = models.BooleanField()
  

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

 def generate_contract(request, id):
    contract = get_object_or_404(Contract, pk=id)
    agreedContacts = contract.agreed_contacts.all()

    return render_to_response('contract.html', {'agreedContacts' : agreedContacts })
  

Теперь в моем шаблоне у меня есть:

   {% for ac in agreedContacts %}
       <strong> {{ ac.agreed }} || {{ ac }}</strong>
  {% endfor %}
  

Проблема в том, что я возвращаю только имя, {{ ac }} работает правильно, но я не возвращаю все остальные поля, связанные с этой записью. Например, согласовано и роль. Как я могу это сделать?

Ответ №1:

ac является Contact экземпляром, а не ContractPartyInvolved единицей. Так ac.agreed не сработает (если у вас также нет agreed поля в контакте, которое вы не показываете).

Вместо того, чтобы следовать соотношению ManyToMany и получать contract.agreed_contacts.all() , вы хотите следовать обратному внешнему ключу из Contact в CPI. Оттуда вы можете получить доступ ко всем полям в CPI, а также продолжить отслеживание связи с контактом и получить имя контакта:

 cpis = contract.contractpartyinvolved_set.select_related().all()


{% for cpi in cpis %}
    {{ cpi.agreed }} || {{ cpi.contact.name }}
{% endfor %}
  

Обратите внимание, что я использовал select_related в первоначальном запросе, чтобы сохранить дальнейшие обращения к базе данных, поскольку вы знаете, что будете следить за отношениями. Если вы также не хотите получать доступ к роли, вы можете ограничить select_related, указав select_related('Contact') .

Комментарии:

1. 1 для select_related. Забыл о дальнейших обращениях к базе данных для извлечения контакта из cpi. Спасибо.

Ответ №2:

в поле зрения:

 involved_contacts = contract.contractpartyinvolved_set.all()
  

в шаблоне:

 {% for icontact in involved_contacts %}
    <strong> {{ icontact.agreed }} || {{ icontact.contact }}</strong>
{% endfor %}