在Django中导航


104

我刚刚在django中完成了我的第一个小型webapp,我喜欢它。我将开始将旧的生产PHP网站转换为django,作为其模板的一部分,有一个导航栏。

在PHP中,我会在模板代码中对照当前URL检查每个nav选项的URL,如果它们对齐,则应用CSS类。太乱了。

django是否有更好的东西,还是处理模板中代码的好方法?

首先,我将如何获取当前URL?


我为此创建了github.com/orokusaki/django-active-menu-它支持嵌套的URL结构,并依赖于对约定的配置(听起来很邪恶),因此您可以根据需要定义站点的层次结构。您只使用<a href="{% url "view:name" %}" {% active_class "view:name" %}>。您可以选择使用它来生成只是" active"数值(通过将False作为第二个参数标签)追加到现有的类属性,但对于大多数的导航链接,例如我所用。
orokusaki 2013年

这个问题似乎与这一问题有关stackoverflow.com/a/9801473/5739875
Evgeny Bobkin

也许此网格有所
guettli

Answers:


74

我使用模板继承来自定义导航。例如:

base.html

<html>
    <head>...</head>
    <body>
        ...
        {% block nav %}
        <ul id="nav">
            <li>{% block nav-home %}<a href="{% url home %}">Home</a>{% endblock %}</li>
            <li>{% block nav-about %}<a href="{% url about %}">About</a>{% endblock %}</li>
            <li>{% block nav-contact %}<a href="{% url contact %}">Contact</a>{% endblock %}</li>
        </ul>
        {% endblock %}
        ...
    </body>
</html>

about.html

{% extends "base.html" %}

{% block nav-about %}<strong class="nav-active">About</strong>{% endblock %}

我非常喜欢这个想法,尤其是为了灵活性,但是它具有较少的DRY权衡。我确实开始在站点中使用它。
匿名

22
我并不热衷于这种方法,因为由同一个子模板处理多个站点部分并不少见。因此,最终您将自定义变量放在视图中,并将条件放在模板中,或者重新排列子模板,使它们都是唯一的……所有这些只是为了检测当前站点部分。最终,模板标签方法变得更加干净。
shacker,2010年

我查看了其他一些解决方案,看来它们都有些破烂。至少,这是非常简单明了的,易于实现/报废。
mlissner

我将重构<ul id="nav">....</ul>为另一个文件,可以说tabs.html。因此,现在包含了base.html {%block nav%}{%include "tabs.html"%}{%endblock%},然后高亮显示了活动标签(在上述about.html中)。我有什么想念的吗?
None-da

@Maddy您正在进行的间接操作足够多,我不确定我会一直保持直觉,但我认为答案与include标记的工作方式有关。查看文档中包含的注释:docs.djangoproject.com/en/dev/ref/templates/builtins/#include就您而言,在您尝试覆盖中的基本模板时about.html,我认为您已经已经有一个渲染的HTML块,而不是等待处理的Django模板块。
jpwatts 2011年

117

您无需执行此操作,请查看以下代码:

tags.py

@register.simple_tag
def active(request, pattern):
    import re
    if re.search(pattern, request.path):
        return 'active'
    return ''

urls.py

urlpatterns += patterns('',
    (r'/$', view_home_method, 'home_url_name'),
    (r'/services/$', view_services_method, 'services_url_name'),
    (r'/contact/$', view_contact_method, 'contact_url_name'),
)

base.html

{% load tags %}

{% url 'home_url_name' as home %}
{% url 'services_url_name' as services %}
{% url 'contact_url_name' as contact %}

<div id="navigation">
    <a class="{% active request home %}" href="{{ home }}">Home</a>
    <a class="{% active request services %}" href="{{ services }}">Services</a>
    <a class="{% active request contact %}" href="{{ contact }}">Contact</a>
</div>

而已。有关实现的详细信息,请查看:
gnuvince.wordpress.com
110j.wordpress.com


2
href的属性缺少django模板括号{{,}}。例如,<aclass="{%活动请求主页%}"href="home">主页</a>应为<a class =“ {%活动请求主页%}” href =“ {{home} }“>首页</a>,tags.py文件还将需要包含一些内容。否则,很好的解决方案!
bsk 2010年

2
+1与应用程序之间的联系更为松散。作为一个初学者,我发现标签需要它自己的应用程序,您不能将其转储到全局的tags.py文件中。我创建了一个名为标签的新应用,一切顺利。docs.djangoproject.com/en/dev/howto/custom-template-tags
Keyo

3
@Keyo,在您的项目中创建一个templatetags目录,然后将您的项目添加到installedapps。那也可以解决问题。或者,如您所说,在您的项目中将主站点创建为应用程序。
Josh Smeaton

5
别忘了添加django.core.context_processors.request到您TEMPLATE_CONTEXT_PROCESSORSsettings.py
影片

1
这对于可能嵌套的州mysite.com(例如mysite.com/blog,作为和)来说是无效的,因为路径将显示为//blog/(分别)每次生成与前者的匹配项。如果您不将其/用作着陆点,那可以没问题,否则我就使用return 'active' if pattern == request.path else ''(我还没有看到与此有关的问题,但我只是使用它进行设置)。
nerdwaller

33

我喜欢上面的110j的清洁度,因此我选择了大部分清洁度,并进行了重构以解决其遇到的3个问题:

  1. 正则表达式将“ home”网址与所有其他网址进行匹配
  2. 我需要将多个URL映射到一个导航选项卡,因此我需要一个更复杂的标记,该标记需要可变数量的参数
  3. 修复了一些网址问题

这里是:

tags.py:

from django import template

register = template.Library()

@register.tag
def active(parser, token):
    args = token.split_contents()
    template_tag = args[0]
    if len(args) < 2:
        raise template.TemplateSyntaxError, "%r tag requires at least one argument" % template_tag
    return NavSelectedNode(args[1:])

class NavSelectedNode(template.Node):
    def __init__(self, patterns):
        self.patterns = patterns
    def render(self, context):
        path = context['request'].path
        for p in self.patterns:
            pValue = template.Variable(p).resolve(context)
            if path == pValue:
                return "active" # change this if needed for other bootstrap version (compatible with 3.2)
        return ""

urls.py:

urlpatterns += patterns('',
    url(r'/$', view_home_method, {}, name='home_url_name'),
    url(r'/services/$', view_services_method, {}, name='services_url_name'),
    url(r'/contact/$', view_contact_method, {}, name='contact_url_name'),
    url(r'/contact/$', view_contact2_method, {}, name='contact2_url_name'),
)

base.html:

{% load tags %}

{% url home_url_name as home %}
{% url services_url_name as services %}
{% url contact_url_name as contact %}
{% url contact2_url_name as contact2 %}

<div id="navigation">
    <a class="{% active request home %}" href="home">Home</a>
    <a class="{% active request services %}" href="services">Services</a>
    <a class="{% active request contact contact2 %}" href="contact">Contact</a>
</div>

也许我们最好用Marcus one来回答,但是它如何与“家”一起工作?它总是活跃的吗?如何使其仅在根URL调用(www.toto.com/和www.toto.com/index)上处于活动状态?这两个答案都不会导致此问题...
DestyNova

20

我是django-lineage的作者,我专门写过这篇文章来解决这个问题:D

我在自己的项目中使用(完全可以接受的)jpwatts方法感到烦恼,并从110j的答案中汲取了灵感。世系看起来像这样:

{% load lineage %}
<div id="navigation">
    <a class="{% ancestor '/home/' %}" href="/home/">Home</a>
    <a class="{% ancestor '/services/' %}" href="/services/">Services</a>
    <a class="{% ancestor '/contact/' %}" href="/contact/">Contact</a>
</div>

ancestor 如果参数与当前页面URL的开头匹配,则将其替换为“活动”。

{% url %}还支持变量参数和全类型反向解析。我添加了一些配置选项,并将其充实了一些,并打包起来供所有人使用。

如果有人感兴趣,请阅读以下内容以了解更多信息:

>> github.com/marcuswhybrow/django-lineage


1
硬编码进入模板的路径:(
CpILL

10

Django 1.5开始

在所有通用的基于类的视图(或从ContextMixin继承的任何基于类的视图)中,上下文字典都包含一个指向View实例的视图变量。

因此,如果使用此类视图,则可以添加likie breadcrumbs作为类级别字段,并在模板中使用它。

示例查看代码:

class YourDetailView(DetailView):
     breadcrumbs = ['detail']
     (...)

在模板中,您可以通过以下方式使用它:

<a href="/detail/" {% if 'detail' in view.breadcrumbs %}class="active"{% endif %}>Detail</a>

如果要“突出显示”父导航项,则需要扩展breadcrumbs列表:

class YourDetailView(DetailView):
     breadcrumbs = ['dashboard', 'list', 'detail']
     (...)

...并在您的模板中:

<a href="/dashboard/" {% if 'dashboard' in view.breadcrumbs %}class="active"{% endif %}>Dashboard</a>
<a href="/list/" {% if 'list' in view.breadcrumbs %}class="active"{% endif %}>List</a>
<a href="/detail/" {% if 'detail' in view.breadcrumbs %}class="active"{% endif %}>Detail</a>

这是一种简单而干净的解决方案,并且与嵌套导航非常兼容。


在该示例中,三个导航项都不都是.active吗?
奥利2013年

是的,但这通常是您希望通过多级导航实现的。当然,breadcrumbs如果需要,您可以放入一件物品。但是你有权利-我的榜样不是最好的。
KonradHałas2013年

@Oli改进示例。
KonradHałas13年

9

您可以将class或id应用于页面的body元素,而不是应用于特定的导航项。

HTML:

<body class="{{ nav_class }}">

CSS:

body.home #nav_home,
body.about #nav_about { */ Current nav styles */ }

8

我这样做是这样的:

<a class="tab {% ifequal active_tab "statistics" %}active{% endifequal %}" href="{% url Member.Statistics %}">Statistics</a>

然后我要做的就是将其添加{'active_tab': 'statistics'}到上下文字典中。

如果您正在使用RequestContext,则可以在模板中获取当前路径,如下所示:

{{ request.path }}

在您看来:

from django.template import RequestContext

def my_view(request):
    # do something awesome here
    return template.render(RequestContext(request, context_dict))

感谢您分享此信息。我使用了这种方法,但是在导航栏中也有一个平面,因此为了检测到并正确突出显示它,我使用了{%ifequal flatpage.url'/ about /'%}。我不喜欢对URL进行硬编码检测,但是它可用于一次破解。
马特·加里森

此解决方案的问题是您已将“统计信息”硬编码到代码中。这违反了使用url标记获取页面的url的目的。
贾斯汀2010年

7

我从上面的nivhab中获取了代码,并删除了一些怪异之处,并将其放入一个干净的templatetag中,对其进行了修改,以便/ account / edit /仍将/ account /选项卡激活。

#current_nav.py
from django import template

register = template.Library()

@register.tag
def current_nav(parser, token):
    import re
    args = token.split_contents()
    template_tag = args[0]
    if len(args) < 2:
        raise template.TemplateSyntaxError, "%r tag requires at least one argument" % template_tag
    return NavSelectedNode(args[1])

class NavSelectedNode(template.Node):
    def __init__(self, url):
        self.url = url

    def render(self, context):
        path = context['request'].path
        pValue = template.Variable(self.url).resolve(context)
        if (pValue == '/' or pValue == '') and not (path  == '/' or path == ''):
            return ""
        if path.startswith(pValue):
            return ' class="current"'
        return ""



#template.html
{% block nav %}
{% load current_nav %}
{% url home as home_url %}
{% url signup as signup_url %}
{% url auth_login as auth_login_url %}
<ul class="container">
    <li><a href="{{ home_url }}"{% current_nav home_url %} title="Home">Home</a></li>
    <li><a href="{{ auth_login_url }}"{% current_nav auth_login_url %} title="Login">Login</a></li>
    <li><a href="{{ signup_url }}"{% current_nav signup_url %} title="Signup">Signup</a></li>
</ul>
{% endblock %}

6

这只是上面Toba提出的CSS解决方案的一个变体:

在基本模板中包括以下内容:

<body id="section-{% block section %}home{% endblock %}">

然后在扩展基本用途的模板中:

{% block section %}show{% endblock %}

然后,您可以根据正文标签使用CSS突出显示当前区域(例如,如果我们有一个链接,其链接为nav-home):

#section-home a#nav-home{
 font-weight:bold;
}


3

到目前为止,谢谢您的回答。我又去了些不同的地方..

在我的模板中:

<li{{ link1_active }}>...link...</li>
<li{{ link2_active }}>...link...</li>
<li{{ link3_active }}>...link...</li>
<li{{ link4_active }}>...link...</li>

一旦确定了逻辑上的哪个页面(通常在urls.py中),我便class="selected"以正确的名称作为上下文的一部分传递 给模板。

例如,如果我在link1页面上,{'link1_active':' class="selected"'}则将添加到模板的上下文中以进行挖掘和注入。

这似乎是工作,这是相当干净。

编辑:为了使HTML不在我的控制器/视图中,我对此做了一些修改:

<li{% if link1_active %} class="selected"{% endif %}>...link...</li>
<li{% if link2_active %} class="selected"{% endif %}>...link...</li>
...

它使模板的可读性降低了一点,但是我同意,最好不要从urls文件中推送原始HTML。


2
实际上应该避免在视图中处理原始HTML,这是此技术所需要的。您是否考虑过编写自定义模板标签?
贾斯汀·沃斯,

你是对的。我已进行编辑以停止通过HTML。我现在只是通过True。我还没有编写任何模板标签,但是可以,这可能是一个不错的起点。
奥利

2

我在同一页面上有多个菜单,这些菜单是通过循环动态创建的。上面与上下文相关的帖子为我提供了快速解决方案。希望这对某人有帮助。(除了活动模板标签之外,我还使用此标签-我的修复解决了动态问题)。看起来比较愚蠢,但是可以。我选择将变量命名为active_something-unique和something-unique,这样它可以与嵌套菜单一起使用。

这是部分视图(足以了解我在做什么):

def project_list(request, catslug):
    "render the category detail page"
    category = get_object_or_404(Category, slug=catslug, site__id__exact=settings.SITE_ID)
    context = {
        'active_category': 
            category,
        'category': 
            category,
        'category_list': 
            Category.objects.filter(site__id__exact=settings.SITE_ID),

    }

这是来自模板的:

<ul>
  {% for category in category_list %}
    <li class="tab{% ifequal active_category category %}-active{% endifequal %}">
      <a href="{{ category.get_absolute_url }}">{{ category.cat }}</a>
    </li>
  {% endfor %}
</ul>

2

我的解决方案是编写一个简单的上下文处理器以根据请求路径设置变量:

def navigation(request):
"""
Custom context processor to set the navigation menu pointer.
"""
nav_pointer = ''
if request.path == '/':
    nav_pointer = 'main'
elif request.path.startswith('/services/'):
    nav_pointer = 'services'
elif request.path.startswith('/other_stuff/'):
    nav_pointer = 'other_stuff'
return {'nav_pointer': nav_pointer}

(不要忘记将您的自定义处理器添加到settings.py中的TEMPLATE_CONTEXT_PROCESSORS。)

然后,在基本模板中,我为每个链接使用ifequal标记,以确定是否要附加“活动”类。当然,这种方法严格限于您的路径结构的灵活性,但是它适用于我相对适度的部署。


我认为这真的很有意义的,这些在全球范围内,所以你可以参考各种方式的网站部分(使用不同的网站的栏目不同的模板,例如+1。
shacker

2

我只想分享对nivhab帖子的一些小改进。在我的应用程序中,我有子导航,我不想仅使用CSS隐藏它们,因此我需要某种“ if”标签来显示项目的子导航与否。

from django import template
register = template.Library()

@register.tag
def ifnaviactive(parser, token):
    nodelist = parser.parse(('endifnaviactive',))
    parser.delete_first_token()

    import re
    args = token.split_contents()
    template_tag = args[0]
    if len(args) < 2:
        raise template.TemplateSyntaxError, "%r tag requires at least one argument" % template_tag
    return NavSelectedNode(args[1:], nodelist)

class NavSelectedNode(template.Node):
    def __init__(self, patterns, nodelist):
        self.patterns = patterns
        self.nodelist = nodelist

    def render(self, context):
        path = context['request'].path
        for p in self.patterns:
            pValue = template.Variable(p).resolve(context)
            if path == pValue:
                return self.nodelist.render(context)
        return ""

基本上可以使用与活动标签相同的方式使用此标签:

{% url product_url as product %}

{% ifnaviactive request product %}
    <ul class="subnavi">
        <li>Subnavi item for product 1</li>
        ...
    </ul>
{% endifnaviactive %}

2

只是原始解决方案的另一种改进。

这可以接受多种模式,最好也将未命名的模式写为用“'”包裹的相对URL,如下所示:

{% url admin:clients_client_changelist as clients %}
{% url admin:clients_town_changelist as towns %}
{% url admin:clients_district_changelist as districts %}

<li class="{% active "/" %}"><a href="/">Home</a></li>
<li class="{% active clients %}"><a href="{{ clients }}">Clients</a></li>
{% if request.user.is_superuser %}
<li class="{% active towns districts %}">
    <a href="#">Settings</a>
    <ul>
        <li><a href="{{ towns }}">Towns</a></li>
        <li><a href="{{ districts }}">Districts</a></li>
    </ul>
</li>
{% endif %}

标签是这样的:

from django import template

register = template.Library()

@register.tag
def active(parser, token):
    args = token.split_contents()
    template_tag = args[0]
    if len(args) < 2:
        raise template.TemplateSyntaxError, "%r tag requires at least one argument" % template_tag
    return NavSelectedNode(args[1:])

class NavSelectedNode(template.Node):
    def __init__(self, urls):
        self.urls = urls

    def render(self, context):
        path = context['request'].path

        for url in self.urls:
            if '"' not in url:
                cpath = template.Variable(url).resolve(context)
            else:
                cpath = url.strip('"')

            if (cpath == '/' or cpath == '') and not (path == '/' or path == ''):
                return ""
            if path.startswith(cpath):
                return 'active'
        return ""

2

我使用jquery突出显示了我的导航栏。此解决方案只是将css类“活动”添加到适合css选择器的项目。

<script type="text/javascript" src="/static/js/jquery.js"></script>
<script>
    $(document).ready(function(){
        var path = location.pathname;
        $('ul.navbar a.nav[href$="' + path + '"]').addClass("active");
    });
</script>

2

@tback的答案有一点增强,没有任何%if%标签:

# navigation.py
from django import template
from django.core.urlresolvers import resolve

register = template.Library()

@register.filter(name="activate_if_active", is_safe=True)
def activate_if_active(request, urlname):
  if resolve(request.get_full_path()).url_name == urlname:
    return "active"
  return ''

像这样在模板中使用它:

{% load navigation %}
<li class="{{ request|activate_if_active:'url_name' }}">
  <a href="{% url 'url_name' %}">My View</a>
</li>

并包括"django.core.context_processors.request"在您的TEMPLATE_CONTEXT_PROCESSORS设置中。


2

我发现最好的方法是使用包含标记:

templates/fnf/nav_item.html

<li class="nav-item">
    <a class="nav-link {% if is_active %}active{% endif %}" href="{% url url_name %}">{{ link_name }}</a>
</li>

这只是我希望呈现的基本引导项。

它获取href值,以及可选的link_name值。is_active是根据当前请求计算的。

templatetags/nav.py

from django import template

register = template.Library()


@register.inclusion_tag('fnf/nav_item.html', takes_context=True)
def nav_item(context, url_name, link_name=None):
    return {
        'url_name': url_name,
        'link_name': link_name or url_name.title(),
        'is_active': context.request.resolver_match.url_name == url_name,
    }

然后在导航中使用它: templates/fnf/nav.html

{% load nav %}
<nav class="navbar navbar-expand-lg navbar-light bg-light">
        <ul class="navbar-nav mr-auto">
                {% nav_item 'dashboard' %}
            </ul>

只是粗略的阅读,但这是否将内容限制为与URL 完全匹配?我通常也将类似这样的导航提示用于深层页面。例如,如果您使用的是/about/company-history//about/what-we-do/
Oli

1
是的,但是is_active可以替换并且可以将其他键添加到字典中。另外,支票可以是context.request.resolver_match.url_name.startswith(x)或其他任何形式。另外,您可以在return语句之前添加代码以建立dict值。此外,您还可以使用不同的模板,即一个top_level_nav.html具有不同的逻辑,等等
Tjorriemorrie

干净简单的解决方案...太好了!
mmw

1

稍微修改Andreas的答案,看来您可以传递从urls.py到template标签的路由名称。在我的示例中my_tasks,然后在模板标记函数中使用反向函数确定URL应该是什么,然后可以将其与请求对象中的URL匹配(在模板上下文中可用)

from django import template
from django.core.urlresolvers import reverse

register = template.Library()

@register.tag
def active(parser, token):
    args = token.split_contents()
    template_tag = args[0]
    if len(args) < 2:
        raise template.TemplateSyntaxError, "%r tag requires at least one argument" % template_tag
    return NavSelectedNode(args[1:])

class NavSelectedNode(template.Node):
    def __init__(self, name):
        self.name = name

    def render(self, context):

        if context['request'].path == reverse(self.name[1]):
            return 'active'
        else:
            return ''

urls.py

url(r'^tasks/my', my_tasks, name = 'my_tasks' ),

template.html

<li class="{% active request all_tasks %}"><a href="{% url all_tasks %}">Everyone</a></li>

也许,更直接的方法是:turnkeylinux.org/blog/django-navbar
jgsogo 2012年

1

我知道我迟到了。我不喜欢任何流行的解决方案:

块的方法似乎是错误的:我认为导航应该是自包含的。

template_tag方法似乎是错误的:我不喜欢,我必须先得到从URL标记的URL。另外,我认为css类应该在模板中定义,而不是在标签中定义。

因此,我编写了一个没有上述缺点的过滤器。True如果网址处于活动状态,则返回,因此可以与一起使用{% if %}

{% load navigation %}
<li{% if request|active:"home" %} class="active"{% endif %}><a href="{% url "home" %}">Home</a></li>

代码:

@register.filter(name="active")
def active(request, url_name):
    return resolve(request.path_info).url_name == url_name

只要确保RequestContext在具有导航功能的页面上使用或在您的请求中启用请求context_processorsettings.py

TEMPLATE_CONTEXT_PROCESSORS = (
    ...
    'django.core.context_processors.request',
)

1

我见过jpwatts110jnivhabMarcus Whybrow的答案,但它们似乎都缺少某些东西:根路径如何?为什么它总是活跃的?

因此,我采用了另一种方法,更容易,使“控制器”自行决定,并且我认为它可以解决大多数大问题。

这是我的自定义标签:

## myapp_tags.py

@register.simple_tag
def nav_css_class(page_class):
    if not page_class:
        return ""
    else:
        return page_class

然后,“控制器”声明所需的CSS类(实际上,最重要的是它在模板中声明其存在)

## views.py

def ping(request):
    context={}
    context["nav_ping"] = "active"
    return render(request, 'myapp/ping.html',context)

最后,我在导航栏中渲染它:

<!-- sidebar.html -->

{% load myapp_tags %}
...

<a class="{% nav_css_class nav_home %}" href="{% url 'index' %}">
    Accueil
</a>
<a class="{% nav_css_class nav_candidats %}" href="{% url 'candidats' %}">
    Candidats
</a>
<a class="{% nav_css_class nav_ping %}" href="{% url 'ping' %}">
    Ping
</a>
<a class="{% nav_css_class nav_stat %}" href="{% url 'statistiques' %}">
    Statistiques
</a>
...

因此,每个页面都有自己nav_css_class要设置的值,如果已设置,则模板将处于活动状态:无需request在模板上下文中进行操作,无需URL解析,也不再需要有关多URL页面或根页面的问题。


1

受此解决方案的启发,我开始使用这种方法:

**Placed in templates as base.html**

{% block tab_menu %}
<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>
{% endblock tab_menu %}

**Placed in your page template**

{% extends "base.html" %}

{% block tab_menu %}
  {% with active_tab="tab1" %} {{ block.super }} {% endwith %}
{% endblock tab_menu %}

0

这是我的努力。我最终在视图中实现了一个包含导航结构的类(带有一些元数据的类)。然后,将其注入模板并渲染出来。

我的解决方案涉及i18n。它可能应该再抽象一点,但是我并没有真正为之烦恼。

views.py:

from django.utils.translation import get_language, ugettext as _


class Navi(list):
    items = (_('Events'), _('Users'), )

    def __init__(self, cur_path):
        lang = get_language()
        first_part = '/' + cur_path.lstrip('/').split('/')[0]

        def set_status(n):
            if n['url'] == first_part:
                n['status'] == 'active'

        for i in self.items:
            o = {'name': i, 'url': '/' + slugify(i)}
            set_status(o)
            self.append(o)

# remember to attach Navi() to your template context!
# ie. 'navi': Navi(request.path)

我使用包括这样的include定义了模板逻辑。基本模板:

{% include "includes/navigation.html" with items=navi %}

实际包含(includes / navigation.html):

 <ul class="nav">
     {% for item in items %}
         <li class="{{ item.status }}">
             <a href="{{ item.url }}">{{ item.name }}</a>
         </li>
     {% endfor %}
 </ul>

希望有人会发现这个有用!我想将这个想法扩展为支持嵌套层次结构等非常容易。


0

创建一个包含模板“ intranet / nav_item.html”:

{% load url from future %}

{% url view as view_url %}
<li class="nav-item{% ifequal view_url request.path %} current{% endifequal %}">
    <a href="{{ view_url }}">{{ title }}</a>
</li>

并将其包含在nav元素中:

<ul>
    {% include "intranet/nav_item.html" with view='intranet.views.home' title='Home' %}
    {% include "intranet/nav_item.html" with view='crm.views.clients' title='Clients' %}
</ul>

并且您需要将此添加到设置中:

from django.conf import global_settings
TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + (
    'django.core.context_processors.request',
)


0

从这个SO问题

{% url 'some_urlpattern_name' as url %}
<a href="{{url}}"{% if request.path == url %} class="active"{% endif %}>Link</a>

对每个链接根据需要重复。


这仅适用于直接匹配。如果后代页面也处于活动状态,则大多数导航系统会将导航项标记为活动。即,如果/blog/posts/2021/04/12是/ blog / nav项目的网址,那么它将处于活动状态。
奥利(Oli)

@Oli是的,它将无法正常工作。例如在计算器导航即QuestionsTagsUsersBadgesUnansweredAsk Question。它不适用于Questions,但对于所有其他导航都可以正常使用。
suhailvs 2013年

0

我还使用jQuery突出显示了它,并且发现它比使用非语义Django模板标签使模板混乱更优雅。

以下代码适用于引导程序3中的嵌套下拉菜单(突出显示父<li>元素和子元素。

// DOM Ready
$(function() {
    // Highlight current page in nav bar
    $('.nav, .navbar-nav li').each(function() {
        // Count the number of links to the current page in the <li>
        var matched_links = $(this).find('a[href]').filter(function() {
            return $(this).attr('href') == window.location.pathname; 
        }).length;
        // If there's at least one, mark the <li> as active
        if (matched_links)
            $(this).addClass('active');
    });
});

在不更改template / html标记的情况下,为当前页面添加click事件return false(或将href属性更改为#)也很容易:

        var matched_links = $(this).find('a[href]').filter(function() {
            var matched = $(this).attr('href') == window.location.pathname;
            if (matched)
                $(this).click(function() { return false; });
            return matched;
        }).length;

0

我将这种混合的组合用于基于类的视图:

class SetActiveViewMixin(object):
    def get_context_data(self, **kwargs):
        context = super(SetActiveViewMixin, self).get_context_data(**kwargs)
        context['active_nav_menu'] = {
            self.request.resolver_match.view_name: ' class="pure-menu-selected"'
        }
        return context

在模板中带有以下内容:

<ul>
    <li{{active_nav_menu.node_explorer }}><a href="{% url 'node_explorer' '' %}">Explore</a></li>
    <li{{active_nav_menu.node_create }}><a href="{% url 'node_create' path %}">Create</a></li>
    <li{{active_nav_menu.node_edit }}><a href="{% url 'node_edit' path %}">Edit</a></li>
    <li{{active_nav_menu.node_delete }}><a href="{% url 'node_delete' path %}">Delete</a></li>
</ul>

0

我的有点类似于以前提交的另一种JS方法..只是没有jQuery ...

假设我们在base.html中具有以下内容:

<div class="pure-u-1 pure-menu pure-menu-open pure-menu-horizontal header" >
    <ul class="">
        <li id="home"><a href="{% url 'article:index' %}">Home</a></li>
        <li id="news"><a href="{% url 'article:index' %}">News</a></li>
        <li id="analysis"><a href="{% url 'article:index' %}">Analysis</a></li>
        <li id="opinion"><a href="{% url 'article:index' %}">Opinion</a></li>
        <li id="data"><a href="{% url 'article:index' %}">Data</a></li>
        <li id="events"><a href="{% url 'article:index' %}">Events</a></li>
        <li id="forum"><a href="{% url 'article:index' %}">Forum</a></li>
        <li id="subscribe"><a href="{% url 'article:index' %}">Subscribe</a></li>
    </ul>
    <script type="text/javascript">
        (function(){
            loc=/\w+/.exec(window.location.pathname)[0];
            el=document.getElementById(loc).className='pure-menu-selected';         
        })();   
    </script>
</div>

我只是按照自己的层次结构来遵循特定的URL模式...主机地址之后...我有我的主要类别,例如住所,新闻,分析等。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.