我已经使用django-mptt对我想要存储文章的标题的部分和子部分等进行了建模。一些章节和章节会有孩子,其他的则不会。
[Home]
[News]
[Politics][Crime][Policing] etc
then [News] > [Politics]
[UKIP][Labour] etc我相信你已经明白了。我已经创建了部分模型
class Section(MPTTModel):
name = models.CharField(max_length=50)
parent = TreeForeignKey('self',null=True, blank=True, related_name='sub_sections')
tree = SectionTreeManager()并将Section.objects.all()传递到模板中:
<ul class="headernav" >
{% recursetree sections %}
<li>
<a href="/section/{{node.name}}" >{{ node.name }}</a>
{% if node.is_leaf_node %}
<ul class="headernav">
{{ children }}
</ul>
{% endif %}
</li>
{% endrecursetree %}
</ul>我可以显示所有节点。我想做的是,根据当前的url ie /section/News获取当前级别上的所有兄弟,上一级别上的所有祖先和下一级别上的所有相关后代。所以如果我选择了News,我会得到
[home][**News**][World][Sports][Culture] <- Level 0
[Politics][Crime][Education] <- Children on Level 1我该怎么做呢?任何帮助都将不胜感激。我正在学习Django,所以如果很明显的话,我会提前道歉。
发布于 2012-10-11 13:56:45
django-page-cms已经使用django-mptt解决了这类问题,所以我建议您看看它是如何完成的。
具体地说,template to render the tree menu是通过一个名为pages_dynamic_tree_menu的custom template tag递归包含的。
这听起来很复杂(自定义的ta-whaaa!),所以我将更详细地分析它。
我们可以认为Page in django-page-cms与您的Section类大致相同。
在99%的页面之间共享的基本模板中,django-page-cms gets you to insert the following snippet
<ul>
{% for page in pages_navigation %}
{% pages_dynamic_tree_menu page %}
{% endfor %}
</ul>django is set by a context processor (一种在template context中为项目中的所有视图添加项目的方法),并包含顶级页面(即那些没有父级的页面)。
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变量。
神奇之处在于if语句,它确保仅当页面是当前页面时才显示子页面( current_page模板变量由呈现Page的django-page-cms视图设置),或者页面是祖先页面。lft和rght属性是由django-mptt提供的,这个MPTT的两个属性是父树节点的左值将小于其子节点的左值,父节点的右值将大于其子节点的右值,您可以通过查看文章Trees in SQL中的下图来直观地验证这一点

Page的get_children_for_frontend()方法调用MPTTModel.getChildren()时进行了一些过滤,以隐藏未发布的Page对象,因此没有什么特别之处。
然后,标记使用pages/dynamic_tree_menu.html模板执行{% include %}的tag equivalent,该模板反过来再次调用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 %}因此,如果您定义了类似的设置(为模板提供顶级部分和当前部分,定义一个“包含”模板标记和标记的匹配模板)并应用一些样式,那么您应该能够使用这种方法来实现您的目标。
https://stackoverflow.com/questions/12828949
复制相似问题