如何使用DRY一个活动项目渲染菜单?

ser*_*ach 42 django django-templates

我想渲染一个像这样的结构:

<a href='/home'>Home</a>
<span class='active'>Community</span>
<a href='/about'>About</a>
Run Code Online (Sandbox Code Playgroud)

社区被选定的菜单项.我有几个模板相同选项的菜单,但我不想为每个模板创建组合:

<!-- for Home template-->
        <span class='active'>Home</span>
        <a href='/comminuty'>Community</a>
        <a href='/about'>About</a>
    ...
<!-- for Community template-->
        <a href='/home'>Home</a>
        <span class='active'>Community</span>
        <a href='/about'>About</a>
    ...
<!-- for About template-->
        <a href='/home'>Home</a>
        <a href='/community'>Community</a>
        <span class='active'>About</span>
Run Code Online (Sandbox Code Playgroud)

我们有永久的菜单项列表,因此,它可以是更有效的方法 - 只创建一个菜单的通用结构,然后使用模板的必需选项呈现菜单.

例如,它可以是允许这样做的标记.

vin*_*ent 71

想出另一种方法,这个答案非常优雅:https://stackoverflow.com/a/17614086/34871

给定一个url模式,例如:

url(r'^some-url', "myapp.myview", name='my_view_name'),
Run Code Online (Sandbox Code Playgroud)

my_view_name通过模板request可以使用(记住你需要使用RequestContext - 使用render_to_response时是隐式的)

然后菜单项可能如下所示:

<li class="{% if request.resolver_match.url_name == "my_view_name" %}active{% endif %}"><a href="{% url "my_view_name" %}">Shortcut1</a></li>
<li class="{% if request.resolver_match.url_name == "my_view_name2" %}active{% endif %}"><a href="{% url "my_view_name2" %}">Shortcut2</a></li>
Run Code Online (Sandbox Code Playgroud)

等等

这样,url可以更改,如果url参数不同,它仍然有效,并且您不需要在其他位置保留菜单项列表.

  • 这是一个很好的解决方案.比其他人更容易,更优雅. (4认同)
  • 使用`request.resolver_match.view_name`作为命名空间名称 (3认同)
  • 这个答案是最容易实现的。我在论坛上阅读了许多帖子,他们提出了复杂的解决方案,但对于我们大多数不打算开发非常大的应用程序的人来说,这就像一种魅力。我想补充一件事:最有可能的是,一个在 html 中需要有 2 个类名,一个用于在未选择的情况下设置菜单项的样式,另一个用于它们被选中/激活的情况。我在下一条评论中举了一个例子。 (2认同)

sem*_*nte 51

使用模板标签

您只需使用以下模板标记:

# path/to/templatetags/mytags.py
import re

from django import template
try:
    from django.urls import reverse, NoReverseMatch
except ImportError:
    from django.core.urlresolvers import reverse, NoReverseMatch

register = template.Library()


@register.simple_tag(takes_context=True)
def active(context, pattern_or_urlname):
    try:
        pattern = '^' + reverse(pattern_or_urlname)
    except NoReverseMatch:
        pattern = pattern_or_urlname
    path = context['request'].path
    if re.search(pattern, path):
        return 'active'
    return ''
Run Code Online (Sandbox Code Playgroud)

所以,在你的模板中:

{% load mytags %}
<nav><ul>
  <li class="nav-home {% active 'url-name' %}"><a href="#">Home</a></li>
  <li class="nav-blog {% active '^/regex/' %}"><a href="#">Blog</a></li>
</ul></nav>
Run Code Online (Sandbox Code Playgroud)

仅使用HTML和CSS

还有另一种方法,只使用HTML和CSS,您可以在任何框架或静态站点中使用.

考虑到你有这样的导航菜单:

<nav><ul>
  <li class="nav-home"><a href="#">Home</a></li>
  <li class="nav-blog"><a href="#">Blog</a></li>
  <li class="nav-contact"><a href="#">Contact</a></li>
</ul></nav>
Run Code Online (Sandbox Code Playgroud)

创建一些基本模板,每个模板用于您网站的每个会话,例如:

home.html
base_blog.html
base_contact.html
Run Code Online (Sandbox Code Playgroud)

所有这些模板都base.html "section" 扩展,例如:

...
<body id="{% block section %}section-generic{% endblock %}">
...
Run Code Online (Sandbox Code Playgroud)

然后,base_blog.html以此为例,您必须具备以下条件:

{% extends "base.html" %}
{% block section %}section-blog{% endblock %}
Run Code Online (Sandbox Code Playgroud)

现在,只使用CSS定义活动菜单项很容易:

#section-home .nav-home,
  #section-blog .nav-blog,
  #section-contact .nav-contact { background-color: #ccc; }
Run Code Online (Sandbox Code Playgroud)

  • 我希望完全匹配,所以我将模式修改为:`pattern ='^'+ reverse(pattern_or_urlname)+'$'`. (3认同)
  • 谢谢你的启发。我已经修改了您的代码以使其甚至可以使用具有语言前缀路径的I18N模式。您可以根据需要编辑评论,以便其他人可以从中受益。http://pastebin.com/8hegST6b (2认同)

ser*_*ach 30

我找到了简单而优雅的DRY解决方案.

这是片段:http: //djangosnippets.org/snippets/2421/

**Placed in templates/includes/tabs.html**

<ul class="tab-menu">
    <li class="{% if active_tab == 'tab1' %} active{% endif %}"><a href="#">Tab 1</a></li>
    <li class="{% if active_tab == 'tab2' %} active{% endif %}"><a href="#">Tab 2</a></li>
    <li class="{% if active_tab == 'tab3' %} active{% endif %}"><a href="#">Tab 3</a></li>
</ul>

**Placed in your page template**

{% include "includes/tabs.html" with active_tab='tab1' %}
Run Code Online (Sandbox Code Playgroud)