用于有条件地呈现或包含另一个模板的模板标签(如果路径存在)

Template tag for conditionally rendering or including another template if the path or paths exist

我正在 Django 应用程序中实现通用下拉菜单。在大多数情况下,页面是通用的,并且它们具有简单的通用 'children' 菜单。但是在某些情况下,我希望能够包含或呈现一组特殊的子项,或者基于页面 slug (page.slug) 的完全不同的模板中的自定义内容。

我考虑过实施包含标记,但我不确定如何在模板标记中执行此操作。我知道在视图中你可以像这样实现它:

blog_post = get_object_or_404(blog_posts, slug=slug)
...
templates = [u"blog/blog_post_detail_%s.html" % str(slug), template]
return render(request, templates, context)

我的标签设计模式很简单:

  1. 在 pages/SLUG/dropdown.html
  2. 内查找
  3. 尝试pages/dropdown_SLUG.html
  4. 如果 none 个文件存在,则不渲染任何内容。

如何从模板标签执行此操作?包含标签是正确的方式,还是 render_tag?

这是我想出的解决方案:

@register.render_tag
def page_menu_special(context, token):
    page = None
    template_name = None
    menu_templates = []

    parts = token.split_contents()[1:]
    for part in parts:
        part = Variable(part).resolve(context)
        if isinstance(part, str):
            template_name = part
        elif isinstance(part, Page) or isinstance(part, CustomPage):
            page = part

    if page and page.slug:
        page_template = str(page.slug) if page.slug != home_slug() else "index"
        method_template = page.get_content_model().get_template_name()

        menu_templates.extend([
            u'pages/menus/dropdown_%s.html' % (page_template),
            u'pages/menus/dropdown/%s.html' % (page_template),
        ])

        if method_template:
            menu_templates.append(method_template)

    if template_name:
        menu_templates.insert(0, template_name)

    try:
        t = select_template(menu_templates)
        return t.render(Context(context))
    except TemplateDoesNotExist:
        return u''

Mezzanine 比较特殊,但逻辑可以重复使用:

  1. 构建潜在模板的路径。
  2. 将列表传递给 select_template
  3. 如果 none 存在,并且 return 为空或合适的呈现内容,则捕获异常。

我仍在尝试弄清楚如何默认使用 另一个 模板标签,从 within 这个定义。所以我可以调用 page_menu_special,如果这个失败了,它会恢复到使用相同参数调用 page_menu,这样就节省了一个 if/else 块。