模板中的 Django for 循环

时间:2021-04-03 14:08:30

标签: django django-views django-templates django-template-filters

我有两个数据集:

ButikPages = ShopPages.objects.filter(UserID_id=User, Parent_id__isnull=True, IsActive=1, URL=shop_page_slug)
SubPages = ShopPages.objects.filter(UserID_id=User, Parent_id__isnull=False, URL=shop_page_slug)

在我的模板中,我尝试过滤这两个列表,如果一个 ButikPages Query 有子页面,它应该是一个下拉菜单,如果不是链接菜单。

<ul class="navbar-nav">
    {% for page in ButikPages %}
    {% for parentpage in SubPages %}
    {% if page.IsActive == 1 and parentpage.Parent_id != page.ID %}
       <li class="nav-item"><a class="nav-link" href="/{{ page.Slug }}/">{{ page.PageTitle }}</a></li>
       {% else %}
       <li class="nav-item dropdown">
       <a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown">{{ page.PageTitle }}</a>
       {% if parentpage.Parent_id == page.ID and parentpage.IsActive == 1 %}
       <ul class="dropdown-menu">
       <li><a class="dropdown-item" href="/{{ parentpage.Slug }}/">{{ parentpage.PageTitle }}</a></li>
       </ul>
      </li>
     {% endif %}
     {% endif %}
     {% endfor %}
     {% endfor %}
      </ul>

如果一个菜单只有一个条目,那是可行的,但如果我有两个子页面,它会出现两次,这是我的理解,因为两个 for 循环。但是如何在没有第二个循环的情况下访问子页面?

PS 如果我只有一种菜单类型会更容易我知道它可以工作,但唯一的区别是我有两种菜单。

问候。

3 个答案:

答案 0 :(得分:1)

您似乎在模型 ShopPages 中构建了一个树状对象列表。 我觉得你应该先在你的视图中创建树状结构,然后在模板中展示,而不是直接在模板中使用两个for循环。

类似于:

shop_pages = ShopPages.objects.filter(UserID_id=User, IsActive=1, URL=shop_page_slug)
parents = list(shop_pages.filter(Parent_id__isnull=True).values('pk', 'Parent_id'))
children = list(shop_pages.filter(Parent_id__in=parents).values('pk', 'Parent_id'))
pages = [
    {
        'pk': parent['pk'],
        'parent_id': parent['Parent_id'],
        'sub_pages': [
            {
                'pk': child['pk'],
                'parent_id': child['Parent_id'],
            } for child in children if child['Parent_id'] == parent['pk']
        ],
    } for parent in parents
]

在您的模板中,执行以下操作:

{% for page in pages %}
    {{ page.pk }}
    ..
    ..
    {% for sub_page in page.sub_pages %}
        {{ sub_page.pk }}
        ..
        ..
    {% endfor %}
{% endfor}

抱歉,我现在无法测试。但是我发现了一些关于儿童位置 for 循环的错误。也许现在可以用了。


我突然发现您可以使用反向 FK 来收集父页面的子页面。因此,如果您不更改 FK related_nameParent_id,其反向字段将是 Parent_id_set,那么您可以这样做:

shop_pages = ShopPages.objects.filter(UserID_id=User, IsActive=1, URL=shop_page_slug)

<ul>
  {% for page in shop_pages %}
  {{ page.pk }}
  ..
    {% for sub_page in page.Parent_id_set.all %}
    {{ sub_page.pk }}
    ..
    {% endfor %}
  {% endfor %}
</ul>

答案 1 :(得分:0)

page 的元素移出嵌套循环:

<ul class="navbar-nav">
{% for page in ButikPages %}
    {% if page.IsActive == 1 %}
    <li class="nav-item"><a class="nav-link" href="/{{ page.Slug }}/">{{ page.PageTitle }}</a></li>
    <li class="nav-item dropdown">
        <ul class="dropdown-menu">
        {% for childpage in SubPages %}
            {% if childpage.Parent_id == page.ID %}
            <li><a class="dropdown-item" href="/{{ childpage .Slug }}/">{{ childpage.PageTitle }}</a></li>
            {% endif %}
        {% endfor %}
        </ul>
    </li>
    {% endif %}
{% endfor %}
</ul>

我不太了解您的 if 条件,可能是我修改了错误的方式。

无论如何,@林敬智展示了重构的正确方法——从已经为简单而愚蠢的页面生成准备的视图中传递数据。避免一遍又一遍地遍历所有子页面。

答案 2 :(得分:-1)

好的,我找到了一个解决方案,但我需要一个更干净的版本:

views.py

def home(request):
    current_site = get_current_site(request)
    try:
        User = MasterData.objects.get(ShopURL=current_site)
        
        SubPages = ShopPages.objects.filter(UserID_id=User, Parent_id__isnull=False)
        parents_id_that_have_childs = ShopPages.objects.filter(Parent_id__isnull=False).values_list('Parent_id', flat=True)
        parents_tmp = ShopPages.objects.filter(ID__in=list(set(parents_id_that_have_childs))).values_list('Slug', flat=True)
        parents = ShopPages.objects.filter(ID__in=list(set(parents_id_that_have_childs)))
        not_parent = ShopPages.objects.filter(UserID_id=User, Parent_id__isnull=True, IsActive=1).exclude(Slug__in=parents_tmp)

查询过多。

模板:

<ul class="navbar-nav">
              {% for page in not_parent %}
               <li class="nav-item"><a class="nav-link" href="{{ page.Slug }}">{{ page.PageTitle }}</a></li>
              {% endfor %}
              {% for parent in parents %}
                    <li class="nav-item dropdown">
                          <a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown">{{ parent.PageTitle }}</a>
                            <ul class="dropdown-menu">
                                {% for parentpage in SubPages %}
                                    {% if parentpage.Parent_id == parent.ID and parentpage.IsActive == 1 %}
                                        <li><a class="dropdown-item" href="/{{ parentpage.Slug }}/">{{ parentpage.PageTitle }}</a></li>
                                    {% endif %}
                                {% endfor %}
                                </ul>
                    </li>
              {% endfor %}
          </ul>