39

我从我的页面中获得了以下 html 片段template.html

<ul class='nav'>
    <li class="active"><a href='/'>Home</a></li>
    <li><a href='/lorem'>Lorem</a></li>

    {% if session['logged_in'] %}
        <li><a href="/account">Account</a></li>
        <li><a href="/projects">Projects</a>
        <li><a href="/logout">Logout</a></li>
    {% endif %}

    {% if not session['logged_in'] %}
        <li><a href="/login">Login</a></li>
        <li><a href="/register">Register</a></li>
    {% endif %}
</ul>

正如您在第 2 行看到的那样,该类处于活动状态。这会突出显示带有 twitter 引导 css 文件的活动选项卡。现在,如果我访问,这将正常工作,但例如www.page.com/当我访问时就不行。www.page.com/login它仍会将主页链接突出显示为活动选项卡。

当然,我可以使用 Javascript/jQuery 轻松地做到这一点,但在这种情况下我宁愿不使用它。

ruby on rails已经有一个可行的解决方案,但我不知道如何将其转换为 python/jinja(我对 jinja/flask 很陌生,根本没有使用过 ruby​​)

4

7 回答 7

88

你看过这个吗?https://jinja.palletsprojects.com/en/3.0.x/tricks/#highlighting-active-menu-items

突出显示活动菜单项

通常,您希望有一个带有活动导航项的导航栏。这真的很容易实现。因为子模板中块之外的分配是全局的并且在评估布局模板之前执行,所以可以在子模板中定义活动菜单项:

{% extends "layout.html" %}
{% set active_page = "index" %}

然后布局模板可以访问active_page. 此外,为该变量定义默认值是有意义的:

{% set navigation_bar = [
    ('/', 'index', 'Index'),
    ('/downloads/', 'downloads', 'Downloads'),
    ('/about/', 'about', 'About')
] -%}

{% set active_page = active_page|default('index') -%}
...
<ul id="navigation">
    {% for href, id, caption in navigation_bar %}
    <li{% if id == active_page %} class="active"{% endif
    %}><a href="{{ href|e }}">{{ caption|e }}</a>
    </li>
{% endfor %}
</ul>
于 2013-09-03T20:07:51.400 回答
23

如果您的菜单分布在整个页面,这是另一种更简单的方法。这种方式使用内联 if 语句打印出active类。

<ul>

<li class="{{ 'active' if active_page == 'menu1' else '' }}">
<a href="/blah1">Link 1</a>
</li>

<li class="{{ 'active' if active_page == 'menu2' else '' }}">
<a href="/blah2"> Link 2 </a>
</li>

</ul>

类 active 用于突出显示

您仍然需要在每个页面上设置变量来标记它们

{% extends "master.html" %}
{% set active_page = "menu1" %}

或者

{% set active_page = "menu2" %}
于 2017-03-28T13:48:10.687 回答
6

对于jinja/flask/bootstrap用户:

如果您像在博客示例http://getbootstrap.com/examples/blog/中那样定义导航, 只需将 id 分配给与您的url_for参数匹配的链接,您只需要修改布局模板,其余的就可以了#魔法。

<nav class="blog-nav">
  <a id="allposts"  class="blog-nav-item" href="{{ url_for('allposts')}}">All Posts</a>
  <a id="index"     class="blog-nav-item" href="{{ url_for('index')}}">Index</a>
  <a id="favorites" class="blog-nav-item" href="{{ url_for('favorites')}}">Favorites</a>
</nav>

在你的基础/布局模板的底部添加这个

<script>
  $(document).ready(function () {
  $("#{{request.endpoint}}").addClass("active"); })
</script>

并且正确的元素将被激活。

编辑: 如果您的布局包含列表中的元素,如下所示:

<nav class="blog-nav">
  <ul class="nav navbar-nav">
    <li>
        <a id="allposts"  class="blog-nav-item" href="{{ url_for('allposts')}}">All Posts</a>
    </li>
    <li>
        <a id="index"     class="blog-nav-item" href="{{ url_for('index')}}">Index</a>
    </li>
    <li>
        <a id="favorites" class="blog-nav-item" href="{{ url_for('favorites')}}">Favorites</a>
    </li>
  </ul>
</nav>

使用parent()函数获取 li 元素而不是链接。

<script>
    $(document).ready(function () {
    $("#{{request.endpoint}}").parent().addClass("active"); })
</script>
于 2014-11-19T10:47:37.237 回答
2

我喜欢@philmaweb的方法,但实际上没有理由要求在每个元素的 id 中复制端点。

base.js:

$(document).ready(function () {
    var scriptElement = $('#baseScript')[0];
    var path = scriptElement.getAttribute('data-path');
    $('a[href="'+path+'"]').addClass("active");
});

base.html

<script id="baseScript" src="{{ url_for('static', filename='js/base.js') }}"
data-path="{{ request.path }}"></script>

为什么不把这个脚本内联呢?当然可以,但允许内联 JS 是一场安全噩梦。您应该在您的网站上使用不允许内联 JS的 CSP(例如Flask-Talisman )。使用data-*属性,以安全的方式做到这一点并不难。

注意:如果您有多个链接指向同一个当前页面,并且您只想将其中一个标记为“活动”,那么这种方法可能不适合您。

于 2019-04-27T20:16:35.567 回答
1

我们可以使用 jinja if 语句让课堂活跃起来

<ul class="nav navbar-nav">
     <li class="{% if request.endpoint=='home' %}active{%endif %}"><a href="{{  url_for('home') }}">home</a></li>
     <li class="{% if request.endpoint=='add_client' %}active{%endif %}"><a href="{{  url_for('add_client') }}">Add Report</a></li>
    </li>
  </ul>
于 2021-01-07T04:18:29.227 回答
0

在页面的某处添加以下 CSS:

a[href $= {{ page_name|default("'/'"|safe) }}]{ [INSERT YOUR ACTIVE STYLING HERE] }

现在,在每个模板上定义page_name,例如:

{% extends "template.html" %} {% set page_name = "gallery" %}

这似乎比其他选项更简单、更容易构建。

编辑:

差不多 1 ​​年后,我回来做这个更简单的修复,因为在每个页面上设置页面名称效率非常低。

而是像这样创建一个函数:

@app.context_processor
def context_processor():
    out = {}
    out['request'] = request # Make sure you import request from flask
    return out

request.url_rule这将允许您将变量隐式传递给 jinja,在这种情况下,我们正在传递包含用户正在访问的路由的访问请求。在之前的版本中,我们只是更改{{ page_name|default("'/'"|safe) }}"{{ request.url_rule|safe }}". 干净多了。

于 2018-04-21T23:20:49.713 回答
0

我不想在子页面中定义 ID,因为我拥有的许多链接都没有特定的子模板。

使用request.base_urland 如果它与_external url_for路由匹配,则将该导航项呈现为活动状态。

{% set nav_items = [
    ("public.home", "Home"),
    ("public.downloads", "Downloads"),
    ("public.about", "About")
    ("account.login", "Login"),
 ]
 -%}

...

   <ul class="navbar-nav mr-auto">
   {% for route, display_text in  nav_items %}
     <li class={% if request.base_url == url_for(route, _external=True) %}"nav-item active"{% else %}"nav-item"{% endif %}>
       <a class="nav-link" href="{{ url_for(route) }}">{{ display_text }}
     {% if request.base_url == url_for(route, _external=True) %}<span class="sr-only">(current)</span>{% endif %}
       </a>
     </li>
   {% endfor %}
   </ul>

于 2020-09-09T20:48:38.340 回答