django-page-cms已经解决了这种类型的问题django-mptt
,所以我建议看看它在那里完成的方式。
具体来说,渲染树形菜单的模板是通过一个名为pages_dynamic_tree_menu
.
这听起来很复杂(自定义 ta-whaaa!),所以我会再分解一下。
我们可以认为 a Page
indjango-page-cms
Section
与您的班级大致相同。
在 99% 的页面之间共享的基本模板中,django-page-cms
让您插入以下代码段:
<ul>
{% for page in pages_navigation %}
{% pages_dynamic_tree_menu page %}
{% endfor %}
</ul>
pages_navigation
由上下文处理器设置(一种将项目添加到 django 项目中所有视图的 模板上下文的方法)并包含顶级页面(即没有父页面的页面)。
标签的pages_dynamic_tree_menu
定义和注册如下:
def pages_dynamic_tree_menu(context, page, url='/'):
"""
Render a "dynamic" tree menu, with all nodes expanded which are either
ancestors or the current page itself.
Override ``pages/dynamic_tree_menu.html`` if you want to change the
design.
:param page: the current page
:param url: not used anymore
"""
lang = context.get('lang', pages_settings.PAGE_DEFAULT_LANGUAGE)
page = get_page_from_string_or_id(page, lang)
children = None
if page and 'current_page' in context:
current_page = context['current_page']
# if this node is expanded, we also have to render its children
# a node is expanded if it is the current node or one of its ancestors
if(page.tree_id == current_page.tree_id and
page.lft <= current_page.lft and
page.rght >= current_page.rght):
children = page.get_children_for_frontend()
context.update({'children': children, 'page': page})
return context
pages_dynamic_tree_menu = register.inclusion_tag(
'pages/dynamic_tree_menu.html',
takes_context=True
)(pages_dynamic_tree_menu)
它的全部意义在于设置 page
和children
变量。
神奇之处在于语句,它确保仅当页面是当前页面(模板变量由呈现 a 的视图设置)或页面是祖先if
时才显示子级。&属性由 提供,该MPTT 的两个属性是父树节点的左值将小于其子节点的左值,父节点的右值将大于其右值它的子节点,您可以通过查看SQL 中的树一文中的下图来直观地验证它:current_page
django-page-cms
Page
lft
rght
django-mptt
通过一些过滤来隐藏未发布的对象的调用get_children_for_frontend()
方法,所以没有什么特别的。Page
MPTTModel.getChildren()
Page
然后标签执行与模板等效的标签,然后再次调用标签,导致整个事情递归:{% include %}
pages/dynamic_tree_menu.html
pages_dynamic_tree_menu
{% load pages_tags cache %}
{% if page.calculated_status %}
<li {% ifequal page current_page %}class="selected"{% endifequal %}>
<a href="{% show_absolute_url page %}">{% show_content page "title" %}</a>
{% if children %}
<ul>{% for child in children %}{% pages_dynamic_tree_menu child url %}{% endfor %}</ul>
{% endif %}
</li>
{% endif %}
因此,如果您定义了类似的设置(为您的模板提供顶级部分和当前部分,定义“包含”模板标签和标签的匹配模板)并应用一些样式,那么您应该能够使用这种方法来完成你的目标。