我有两个数据集:
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 如果我只有一种菜单类型会更容易我知道它可以工作,但唯一的区别是我有两种菜单。
问候。
答案 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_name
的 Parent_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>