Задать вопрос
@turbidit
Asterisk, MikroTik, Python

Как вывести ForeignKey для ветвей дерева MPTT?

Добрый день.

Есть древовидная модель подразделений и связанных с ними контактов:

class Subdivision(MPTTModel):
    subdivision = models.CharField(verbose_name="subdivision", max_length=255)
    parent = TreeForeignKey("self", null=True, blank=True, related_name="children")

class Contact(models.Model):
    full_name = models.CharField(verbose_name="full name", max_length=255, unique=True)
    subdivision = models.ForeignKey(Subdivision)


Формируем вывод:

def view_list_contacts(request):
    subdivisions = Subdivision.objects.all()
    contacts = Contact.objects.order_by('id')
    return render(request, URL_RENDER['view_list_contacts'], locals())


Для того чтобы вывести в шаблоне принадлежащие текущей ноде контакты, мне приходится шерстить их все по кругу:

<ul>
    {% recursetree subdivisions %}
        <li>
            {{ node.subdivision }}
            {% for contact in contacts %}
                {% if contact.subdivision.id == node.id %}
                    {{ contact.full_name }}
                {% endif %}
            {% endfor %}

            {% if not node.is_leaf_node %}
                <ul class="children">
                   {{ children }}
                </ul>
            {% endif %}
        </li>
    {% endrecursetree %}
</ul>


Выглядит кривовато. Есть менее костыльное решение?
  • Вопрос задан
  • 633 просмотра
Подписаться 2 Оценить Комментировать
Решения вопроса 1
@deliro
Да. Это называется обратной связью. Если ты связываешься так:
class A:
    b = ForeignKey(B)

То множество объектов типа A, которые ссылаются на b получаются в django так:
b.a_set.all()  # Или filter, get. В общем, обычный QuerySet


То есть, в твоём случае так:
{% for contact in node.contact_set.all %}
    {{ contact.full_name }}
{% endfor %}

Но в этом случае при каждой итерации {% for contact in node.contact_set.all %} будет посылаться запрос в базу, поэтому нужно добавить в
subdivisions = Subdivision.objects.all()
prefetch_related:
subdivisions = Subdivision.objects.all().prefetch_related('contact_set')

Вот так будет оптимизированно.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы