Шаблон Django: отображать объекты в каскаде с внешним ключом - PullRequest
0 голосов
/ 20 сентября 2018

Я пытаюсь отобразить некоторые объекты django в моем шаблоне, которые связаны с Foreign Key field.

Я попытался сделать простой пример, чтобы проиллюстрировать, что я хотел бы получить в своем шаблоне сaccordion html.

Моя модель django:

class Grandparent(models.Model):
    name = models.CharField(...)
    age = models.IntegerField(...)

    def __str__(self):
        return f"{self.name} : {self.age}"


class Parent(models.Model):
    name = models.CharField(...)
    age = models.IntegerField(...)
    grandparent = models.ForeignKey(Grandparent, related_name='grandparent')

    def __str__(self):
        return f"{self.name} : {self.age}"


class Child(models.Model):
    name = models.CharField(...)
    age = models.IntegerField(...)
    parent = models.ForeignKey(Parent, related_name='parent')

    def __str__(self):
        return f"{self.name} : {self.age}"

Как видите, ребенок зависит от родителя, который зависит от деда.

Мой HTML-шаблон:

Теперь я хотел бы отобразить нечто подобное в моем HTML-шаблоне:

enter image description here

Так что мой HTML выглядит так, как показано ниже, и я не могу получить то, что хочу:

{% for grandparent in grandparent_list %}
<div class="accordion-publication panel-group" id="accordion" role="tablist" aria-multiselectable="true">
  <div class="panel-primary">
    <div class="panel-heading" role="button" id="head_0" data-toggle="collapse">
      <span>{{ grandparent }}</span>
    </div>
    {% for parent in parent_list %}
    <div class="panel-collapse collapse in" role="tabpanel" aria-expanded="true">
      <div class="panel-body">
        <div class="panel panel-default">
          <div class="panel-heading collapsed" role="button" data-toggle="collapse" aria-expanded="true">
            <span class="panel-title">{{ parent }}</span>
          </div>
          <div class="panel-collapse collapse in" role="tabpanel" aria-labelledby="head_0">
            <div class="panel-body">
            {% for child in child_list %}
              <table class="table table-condensed">
                <tbody>
                  <tr>
                    <td class="col-md-1"> {{ child }}</td>
                  </tr>
                </tbody>
              </table>
            {% endfor %}
            </div>
          </div>
        </div>
      </div>
    </div>
    {% endfor %}
  </div>
</div>
{% endfor %}

Этот HTML-код немного общий, но я непреодолеть, чтобы получить отношения между каждым уровнем и подуровнем, чтобы отобразить for each grandparent, отобразить each parents associated, затем отобразить each child associated to each parent ..

My django view:

Мой класс в моем представлении django выглядит так:

def get_context_data(self, **kwargs):

    self.count_number_document()
    self.flag_publication()
    kwargs['child_list'] = Child.objects.all().order_by('parent__grandparent__name')
    kwargs['parent_list'] = Parent.objects.all().order_by('name')
    kwargs['grandparent_list'] = Grandparent.objects.all()

    return super(MyClassView, self).get_context_data(**kwargs)

Ответы [ 2 ]

0 голосов
/ 20 сентября 2018

Во-первых, используйте «children» на всех ваших связанных именах, чтобы grandparent.children.all () давал всем потомкам grand parent, то есть экземплярам Parent.Аналогично для класса Parent и Child.

Подойдя к представлению, отправьте только бабушку и дедушку в контекст.Но подождите, это приведет к N + 1 запросам, если вы получите доступ к детям и их детям.Так что используйте prefetch при отправке бабушке и дедушке.

grandparents = Grandparent.objects.all().prefetch_related(Prefetch('children', queryset=Parent.objects.all().prefetch_related('children'))) 
0 голосов
/ 20 сентября 2018

Благодаря ответу Alasdair я нашел решение.

Во-первых, я должен определить мою модель следующим образом (related_name настройка):

class Grandparent(models.Model):
    name = models.CharField(...)
    age = models.IntegerField(...)

    def __str__(self):
        return f"{self.name} : {self.age}"


class Parent(models.Model):
    name = models.CharField(...)
    age = models.IntegerField(...)
    grandparent = models.ForeignKey(Grandparent, related_name='parents')

    def __str__(self):
        return f"{self.name} : {self.age}"


class Child(models.Model):
    name = models.CharField(...)
    age = models.IntegerField(...)
    parent = models.ForeignKey(Parent, related_name='children')

    def __str__(self):
        return f"{self.name} : {self.age}"

Затем, на мой взгляд.py файл, я просто должен установить:

kwargs['grandparent_list'] = Grandparent.objects.all().order_by('name')

И, наконец, в моем HTML-шаблон:

{% for grandparent in grandparent_list %}
<div class="accordion-publication panel-group" id="accordion" role="tablist" aria-multiselectable="true">
  <div class="panel-primary">
    <div class="panel-heading" role="button" id="head_0" data-toggle="collapse">
      <span>{{ grandparent }}</span>
    </div>
    {% for parent in grandparent.parents.all %}
    <div class="panel-collapse collapse in" role="tabpanel" aria-expanded="true">
      <div class="panel-body">
        <div class="panel panel-default">
          <div class="panel-heading collapsed" role="button" data-toggle="collapse" aria-expanded="true">
            <span class="panel-title">{{ parent }}</span>
          </div>
          <div class="panel-collapse collapse in" role="tabpanel" aria-labelledby="head_0">
            <div class="panel-body">
            {% for child in parent.children.all %}
              <table class="table table-condensed">
                <tbody>
                  <tr>
                    <td class="col-md-1"> {{ child }}</td>
                  </tr>
                </tbody>
              </table>
            {% endfor %}
            </div>
          </div>
        </div>
      </div>
    </div>
    {% endfor %}
  </div>
</div>
{% endfor %}
...