如何实现导航“选中”项目

时间:2011-12-08 19:54:44

标签: python navigation pyramid mako

我需要在网页上实现导航菜单,可能有多个级别的标签。每当CSS在我的控制之下时,我都会使用CSS方式,但现在我在使用现有的CSS库时会遇到问题(在这种情况下是Twitter的Bootstrap)。

首先,这是我使用的CSS方式。示例HTML:

<html>
<head>
    <title>Example page</title>
</head>
<body class="articles">

<div class="navigation">
    <ul>
        <li class="frontpage"><a href="#">Frontpage</a></li>
        <li class="articles"><a href="#">Articles</a></li>
    </ul>
</div>

<p>Blah blah.</p>

</body>
</html>

...和CSS:

body.frontpage div.navigation li.frontpage,
body.articles div.navigation li.articles {
    background-color:red;
    color:white;
}

足够简单。在适当的时候,只需要改变身体的类别。

现在,Bootstrap似乎使用基于类的样式来选择导航项(topbar,tabs,pills)。例如:

...
<div class="navigation">
    <ul class="tabs">
        <li class="active"><a href="#">Frontpage</a></li>
        <li><a href="#">Articles</a></li>
    </ul>
</div>
...

我最初想过做类似

的事情
navigation = ('frontpage',)
# or
navigation = ('articles', 'categories', 'foo',)
在控制器中

然后将这个元组传递给模板,但不知怎的,它有“做错了”这种氛围。

所以问题是:因为我实际上必须在模板中打印类选择,所以我如何跟踪当前位置(如在导航树中的位置是这个页面),因为页面可能有多级标签或其他导航项?有没有一种首选的方法呢?

我在路线风格中使用Pyramid和Mako模板,但通用答案也很受欢迎。

2 个答案:

答案 0 :(得分:3)

我做了类似的事情(Pyramid&amp; Bootstrap),但只针对一个级别的导航。

我做的第一件事是创建一个“视图”对象,它将参数传递给每个渲染,例如title,header,get_data等。例如

class View_Controller(object):
    def __init__(self, request, **kwargs):
        self.request = request
        self.nav = kwargs.get('nav', None)

    @property
    def page(self):
        return request.GET.get('page', 1)

@view_config(route_name='home', renderer='templates/homepage.mako')
def Homepage_View(request):
    view = View_Controller(request, nav='homepage')
    stuff = DBSession.query(Stuff).all()
    return {'view': view, 'stuff': stuff}

我在每个页面渲染中设置属性nav,但在没有激活导航元素时使用nav = None。然后我在Mako中为导航元素创建了一个模板:

<%def name="navelements(things)">
% for a in things:
<li${' class="active"' if nav == a[1] else '' | n }><a href="#">a[0]</a></li>
% endfor
</%def>

“thing”是导航中所有元素的元组。 [0]是显示名称,[1]是内部名称。转义html字符需要“| n”。例如:

<%! things = [['Frontpage', 'homepage'], ['Articles', 'arts'], ['Categories', 'cats'], ['Foo', 'foo']] %>

% if things:
<div class="navigation">
  <ul class="tabs">
    ${navelements(things)}
  </ul>
</div>
% else:
<hr />
% endif

现在,您可以通过视图在模板或控制器中设置内容。我有“if things”子句,以防你需要在每个页面上调用的通用选项卡模板;您可以通过在控制器中设置things = None来禁用选项卡。

这只是一个级别的标签,但你可以通过使一个更复杂的列表来做同样的事情。我会让事情变得更复杂,所以与目前的情况相比,它看起来像是:

things = [['displayname1', 'elementname1', things1], ['displayname2', 'elementname2', things2], ...]

然后我会使navelements递归(Mako不支持,所以我只需要复制navelements函数并让它们互相调用)并实现对多级导航的支持:

<%def name="navelements1(things, level=0)">
% for a in things:
<li${' class="active"' if nav[level] == a[1] else '' | n }><a href="#">a[0]</a></li>
   % if a[2]:
     <ul class="tabs">
       ${navelements2(a[2], level+=1)}
     </ul>
   % endif
% endfor
</%def>

导航看起来像:

nav = ['frontpage', 'best', None, ...]

希望能回答你的问题。只需确保您的列表长度正确,这样您就不会出错。

答案 1 :(得分:0)

您可以使用 渲染时使用的系统值 ,通过访问变量view.__name__来获取模板中的视图名称。

然后更改活动链接(例如在jinja2中但它应该类似)

<li {% if view.__name__ == "fixtures" %} class="active" {% endif %}>
  <a href="#">Link</a>
</li>

更多信息,请访问 http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/templates.html#system-values-used-during-rendering