使用索引页面子链接创建Django Wagtail侧边栏



我正在使用django wagtail构建站点,并且很难弄清楚如何添加侧边栏菜单,该侧栏菜单将列出父母索引页面的所有子页面。例如,我有一个standard_index_page.html,我创建了一个带有admin的父页面,然后我使用standard_page.html模板添加了该页面。

在我的standard_index_page.html模板中,我有以下代码

{% standard_index_listing calling_page=self %}

,它显示了所有带有链接的孩子页面,但我也想显示子页面上所有子链接的列表。

我希望这是有道理的,有人可以伸出援手。谢谢。

本质上,您穿越了django-treebeard提供给Wagtail的页面层次结构的树结构。

许多前端框架不允许在最佳实践之外考虑多个菜单。但是,借助SmartMenus等库,您可以用稍有肘部润滑脂显示此结构。

为了我的需求,对此没有简单的解决方案。因此,虽然我想分享一个关于我如何解决的示例,但它可能缺少解释。如果您有任何疑问,我很乐意回答它们。

我为此挣扎了一段时间,虽然可能有更容易的方法穿越树,但随着需求的扩展,我构建了以下方法。它使我们能够穿越网站中的所有实时页面,检查菜单中当前页面何时呈现,并可以对渲染进行细粒度的控制。

这是我们要做的:

  • 创建一些将获取网站root的模板标签当前网站循环通过网站的直接儿童root 循环通过任何较低的儿童,而> 通过当前Menuitem的子女循环在每个级别发现时

在您的基本模板中,这意味着我们需要:

  • {% load demo_tags %}导入我们的自定义模板标签
  • {% top_menu calling_page=self %}致电获取并渲染全部网站root 的直接孩子。这些是标准菜单栏中显示的项目。
  • 在模板中调用{% top_menu_children parent=menuitem %}{% top_menu %}渲染到获取并渲染全部第二和下层儿童页面。这包括在父母菜单项上徘徊时要显示的所有菜单项。

这是我为遍历页面层次结构的所有级别而创建的自定义 demo_tags.py 。这样做的好处是,它不需要提供任何自定义上下文数据;它可以使用Wagtail!

从开箱即用
@register.assignment_tag(takes_context=True)
def get_site_root(context):
    ''' 
    Returns a core.Page, not the implementation-specific model used
    so object-comparison to self will return false as objects would differ  
    '''
    return context['request'].site.root_page

def has_menu_children(page):
    '''
    Returns boolean of whether children pages exist to the page supplied
    '''   
    return page.get_children().live().in_menu().exists()    

@register.inclusion_tag('info_site/tags/top_menu.html', takes_context=True)
def top_menu(context, parent, calling_page=None):
    '''
    Retrieves the top menu items - the immediate children of the parent page
    The has_menu_children method is necessary in many cases. For example, a bootstrap menu requires
    a dropdown class to be applied to a parent
    '''
    root = get_site_root(context)
    try:
        is_root_page = (root.id == calling_page.id)
    except:
        is_root_page = False
    menuitems = parent.get_children().filter(
        live=True,
        show_in_menus=True
    ).order_by('title')
    for menuitem in menuitems:
        menuitem.show_dropdown = has_menu_children(menuitem)
    return {
        'calling_page': calling_page,
        'menuitems': menuitems,
        'is_root_page':is_root_page,
        # required by the pageurl tag that we want to use within this template
        'request': context['request'],
    }

@register.inclusion_tag('my_site/tags/top_menu_children.html', takes_context=True)
def top_menu_children(context, parent, sub=False, level=0):
    ''' Retrieves the children of the top menu items for the drop downs '''
    menuitems_children = parent.get_children().order_by('title')
    menuitems_children = menuitems_children.live().in_menu()
    for menuitem in menuitems_children:
        menuitem.show_dropdown = has_menu_children(menuitem)
    levelstr= "".join('a' for i in range(level)) # for indentation
    level += 1
    return {
        'parent': parent,
        'menuitems_children': menuitems_children,
        'sub': sub,
        'level':level,
        'levelstr':levelstr,
        # required by the pageurl tag that we want to use within this template
        'request': context['request'],
    }

本质上,呈现三个级别的页面:

  • {% get_site_root %}
  • 调用了站点根
  • {% top_menu %}
  • 调用了一级儿童
  • 第二和下级儿童由{% top_menu_children %}调用,这在菜单中显示的任何页面都称为"儿童" 。。

为了做到这一点,我们需要创建由top_menutop_menu_children模板标签渲染的模板。

请注意 - 所有这些都是为Bootstrap 3的Navbar类构建的,并根据我的需求进行自定义。只需自定义这些满足您的需求即可。整个菜单构建过程由{% top_menu_children %}调用,因此将此标签放在您想要呈现菜单的基础模板中。更改top_menu.html以反映菜单的整体结构以及如何渲染每个menuitem。更改children_items.html,以反映您希望所有顶级物品的孩子在任何深度渲染的方式。

my_site/tags/top_menu.html

{% load demo_tags wagtailcore_tags static %}
{% get_site_root as site_root %}
{# FOR TOP-LEVEL CHILDREN OF SITE ROOT; In a nav or sidebar, these are the menu items we'd generally show before hovering. #}
<div class="container">
    <div class="collapse navbar-collapse" id="navbar-collapse-3">
        <ul class="nav navbar-nav navbar-left">
            {% for menuitem in menuitems %}
                <li class="{% if menuitem.active %}active{% endif %}">
                    {% if menuitem.show_dropdown %}
                        <a href="{{ menuitem.url }}">{{ menuitem.title }}
                            <span class="hidden-lg hidden-md hidden-sm visible-xs-inline">
                                <span class="glyphicon glyphicon-chevron-right"></span>
                            </span>
                        </a>
                        {% top_menu_children parent=menuitem %}
                    {% else %}
                        <a href="{% pageurl menuitem %}">{{ menuitem.title }}</a>
                    {% endif %}
                </li>
            {% endfor %}
        </ul>
    </div>
</div>

my_site/tags/childres_items.html

{% load demo_tags wagtailcore_tags %}
{# For second- and lower-level decendents of site root; These are items not shown prior to hovering on their parent menuitem, hence the separate templates (and template tags) #}
<ul class="dropdown-menu">
    {% for child in menuitems_children %}
        {% if child.show_dropdown %}
            <li>
                <a href="{% pageurl child %}">
                    {% for i in levelstr %}&nbsp&nbsp{% endfor %}
                    {{ child.title }}
                    <span class="glyphicon glyphicon-chevron-right"></span>
                </a>
                {# On the next line, we're calling the same template tag we're rendering. We only do this when there are child pages of the menu item being rendered. #}
                {% top_menu_children parent=child sub=True level=level %}
                {# ^^^^ SmartMenus is made to render menus with as many levels as we like. Bootstrap considers this outside of best practices and, with version 3, has deprecated the ability to do so. Best practices are made to be broken, right :] #}
            </li>
        {% else %}
            <li>
                <a href="{% pageurl child %}">
                    <!-- Allows for indentation based on depth of page in the site structure -->
                    {% for i in levelstr %}&nbsp&nbsp{% endfor %}
                    {{ child.title }}
                </a>
            </li>
        {% endif %}
    {% endfor %}
</ul>

现在,在您的基本级模板中(假设您正在使用;如果没有使用,请访问:))您可以穿越菜单,同时将混乱清除到inclusion_tag s使用的模板上。

my_site/base.html

<ul class="nav navbar-nav navbar-left">
    {% for menuitem in menuitems %}
        <li class="{% if menuitem.active %}active{% endif %}">
            {% if menuitem.show_dropdown %}
                <a href="{{ menuitem.url }}">{{ menuitem.title }}
                    <span class="hidden-lg hidden-md hidden-sm visible-xs-inline">
                        <span class="glyphicon glyphicon-chevron-right"></span>
                    </span>
                </a>
                {% top_menu_children parent=menuitem %}
            {% else %}
                <a href="{% pageurl menuitem %}">{{ menuitem.title }}</a>
            {% endif %}
        </li>
    {% endfor %}
</ul>

我写了一篇博客文章 - 查看它以获取更多详细信息。或者,前往thermaline.com进行行动,尽管我认为目前还没有多个级别的深度。如果有的话,它们会自动渲染:)

现在,此示例是针对纳维尔的,但是可以很容易地适合侧边栏。

您需要做的就是:

  • 在您的基本模板中包括demo_tags
  • 致电{% top_menu %}您希望在哪里呈现菜单。
  • 自定义top_menu.htmlchildren_items.html渲染首先,然后所有后续页面的页面。

大喊大叫Tivix在两级菜单上的帖子,这对我来说是一个很棒的起点!

最新更新