【问题标题】:Highlight current menu item in sidebar突出显示侧边栏中的当前菜单项
【发布时间】:2012-08-12 23:40:10
【问题描述】:

我正在使用 django 和 Twitter Bootstrap。我当前的视图类似于examples provided 之一。看这个例子,可以想象用户点击侧边栏中的一个链接来查看不同的视图,每个视图都带有相同的侧边栏。可以想象,所选链接随后会像使用代码的示例一样突出显示:

<li class="active"><a href="/sample/link/here/">Link</a></li>

活动类需要附加到正确的菜单项。我如何将这个“活动”类分配给正确的菜单项?最初,我尝试从我的视图中使用一个变量来用 jquery 分配它:

$(document).ready(function() {
    $("#{{ current_view }}_nav").addClass('active');
});

<li id="linkone_nav"><a href="/sample/link/here/">Link</a></li>

这似乎很麻烦。它要求我将 id 从视图传递给模板。还有很多 id 需要管理。是否有更好/更首选的方式来分配这个活动类?

【问题讨论】:

    标签: jquery django django-templates twitter-bootstrap


    【解决方案1】:

    我认为您在示例代码中对 href 使用 # 会使问题变得模糊不清。我假设您的真实场景是实际的真实链接,并根据活动 URL 自动突出显示它们。如果这是正确的,那么就这样做:

    {% url something as url %}
    <li{% if request.path == url %} class="active"{% endif %}><a href="{{ url }}">Link1</a></li>
    

    其中,“something”是 urlpattern 或视图的虚线路径等的名称。显然,这假定您正在反转 URL,因此,如果您使用的是静态 URL,您只需硬编码它:

    <li{% if request.path == "/my/full/url/path/" %} class="active"{% endif %}><a href="/my/full/url/path/">Link1</a></li>
    

    【讨论】:

    • 啊,这更符合我的要求。很抱歉模棱两可。刚刚从引导程序源中复制以供参考。我会试一试!
    【解决方案2】:

    如果您已将项目组织到由其他模板扩展的 base.html 模板中,例如appname/pagename.html,您可以使用以模板为中心的方法来突出显示活动的导航元素。

    这种方法为您提供了一些解耦优势,我已在此答案末尾详细说明。

    我发现这种方法对于处理在大部分或全部网站上保持相同的广泛导航项非常有用。对于更详细的导航元素,例如呈现从数据存储中收集的动态项目列表,这可能不是一个合适的解决方案。

    在您的 base.html 模板中,为每个导航元素添加一个块,为这些块提供唯一的名称:

    <ul class="nav">
      <li class="{% block navbar_class-home %}{% endblock %}">
        <a href="#">Home</a>
      </li>
      <li class="{% block navbar_class-about %}{% endblock %}">
        <a href="#">About</a>
      </li>
      <li class="{% block navbar_class-pricing %}{% endblock %}">
        <a href="#">Pricing</a>
      </li>
    </ul>
    

    在您的appname/pagename.html 模板中,如果您希望其中一个导航元素显示为活动状态,请使用active 作为内容覆盖相应的块。例如,要突出显示“关于”项:

    {% block navbar_class-about %} active {% endblock %}
    

    当您使用呈现该模板的视图时,它将呈现如下:

    <ul class="nav">
      <li class="">
        <a href="#">Home</a>
      </li>
      <li class=" active ">
        <a href="#">About</a>
      </li>
      <li class="">
        <a href="#">Pricing</a>
      </li>
    </ul>
    

    这提供了不依赖于 JavaScript 的初始呈现。 (如果你正在做一个单页应用程序,你可以使用 JavaScript 修改导航栏类。)

    对于许多(但不是全部)情况,这可能是与视图逻辑更好的分离表示:

    • 您可以修改视图以将站点导航数据附加到模板上下文,但这样做会强烈地将演示文稿与视图层耦合,并使创建可重用应用程序或集成第三方应用程序变得更加困难。

      视图已经在选择一个命名模板,这意味着您已经将一些与导航相关的信息传递给模板层。这可能就是您所需要的。

    • 您可以使用模板上下文处理器来获取有关视图的一些信息,但这只是将强耦合转移到系统的另一层,而不是留在模板层中。

    【讨论】:

      【解决方案3】:

      更好的解决方案,更少的代码。与 Bootstrap 配合得很好。只需更改“addClass”查询以选择您的菜单项。

      在 Javascript 上,创建这个函数:

      var highlight_menu = function(path) {
          /* Highlight current link */    
          $('.nav li').removeClass('active');
          $('.nav li:has(a[href="' + path + '"])').addClass('active')
      };
      

      在base.html上,以当前路径调用JS函数:

      <script>
          highlight_menu('{{request.path}}');
      </script>
      

      【讨论】:

        【解决方案4】:

        FWIW,Twitter Bootstrap 页面本身具有通过使用Scrollspy plugin 提供的此功能。

        否则,您可以只听菜单中的点击事件。

        $('.nav').on('click', 'li:has(a[href^="#"])', function (e) {
          $('.nav li').removeClass('active');
          $(this).addClass('active');
        });
        

        【讨论】:

        • 谢谢。不过,这不太适用。我的链接不是同一页面上的锚点。他们正在引用共享相同菜单的其他页面(如果有意义的话)。
        【解决方案5】:

        为您的菜单添加一个 sn-p:

        <li class="{% if opt=='link1' %} active{% endif %}"><a href="#/?opt=link1">Link1</a></li>
        <li class="{% if opt=='link2' %} active{% endif %}"><a href="#/?opt=link2">Link2</a></li>
        <li class="{% if opt=='link3' %} active{% endif %}"><a href="#/?opt=link3">Link3</a></li>
        ...
        

        将其包含在您的基本模板中:

        {% include "menu.html" with opt=request.GET.opt %}
        

        如您所见,您不需要使用 $( document ).ready(...)。

        不要忘记向您的 TEMPLATE_CONTEXT_PROCESSORS 添加请求:

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

        【讨论】:

          【解决方案6】:

          您可以考虑以下方法来解决 Django 中的问题。

          不使用 javascript 也能正常工作。只需使用纯 Django,您就应该能够解决大多数需要突出显示菜单选项的情况。

          在这个例子中,我使用的是 Bootstrap 4,但这并不重要。你可以使用自己的 CSS,你会没事的。这里的想法只是展示使用 request.resolver_match.url_name as url_name 来实现您的需要。

          {% with request.resolver_match.url_name as url_name %}
             <ul class="navbar-nav mr-auto">
                <li class="{% if url_name == 'your url' %}nav-item active{% else %}nav-item{% endif %}">
                 <a class="nav-link" href="{% url 'your url 1' %}">Menu option 1</a>
                </li>
                <li class="{% if url_name == 'your url' %}nav-item active{% else %}nav-item{% endif %}">
                 <a class="nav-link" href="{% url 'your url 2' %}">Menu option 2</a>
                </li>
             </ul>
          {% endwith %}
          

          【讨论】:

            【解决方案7】:

            我为此使用了一个 simple_tag。也许有人会觉得它有帮助。

            创建一个文件 isactive.py 并放在应用模板路径级别的 templatetags 目录中。

            from django import template
            from django import urls
            register = template.Library()
            
            @register.simple_tag
            def isactive(page_name, request_url):
                rev_url = ''
                try:     
                    rev_url = urls.reverse(page_name)
                except:
                    return ''
                if (rev_url == request_url):
                        return 'active'
                return ''
            

            在你的 html 模板中

            {% load isactive %}
            

            加载静态后 在你的菜单中

            <a href="{% url 'my_table_list' %}" class="nav-link {% isactive 'my_table_list' request.path %}">
            

            渲染时 - django 正在执行函数 isactive 其中第一个参数是页面名称,另一个是路径。在 isactive 函数内部,名称被解析和比较。当它匹配时,将返回活动字符串并将其放置在生成的 html 中。 你必须在每个导航链接中调用。

            页面名称取自您应用的 urls.py 中的 urlpatterns

            urlpatterns = (
                ...
                path("my_table/list/", views.mytableListView.as_view(), name="my_table_list"),
                ....
            

            【讨论】:

            • 如果 URL 中有任何 GET 参数会怎样?也许你应该替换你的条件来检查request_url是否与rev_url开头相同
            • 好问题!但是 django 文档说:“ HttpRequest.path 表示请求页面的完整路径的字符串,不包括方案、域或查询字符串。示​​例:“/music/bands/the_beatles/”
            • ...Still.. 如果传递了对象的 id,则只需要比较起始字符串。但是我们可以以重复结束....
            猜你喜欢
            • 2021-04-07
            • 2016-06-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-11-18
            • 2012-09-17
            • 1970-01-01
            相关资源
            最近更新 更多