【问题标题】:Factorizing a header menu in Django template在 Django 模板中分解标题菜单
【发布时间】:2013-05-12 16:21:23
【问题描述】:

我正在使用 django 构建一个网站,每个页面顶部都有一个标题,这基本上是一个带有几个链接的菜单,在整个页面中保持不变。

但是,根据您所在的页面,我想通过添加“活动”类来突出显示菜单上的相应链接。为此,我目前正在执行以下操作:每个页面都有一个完整的菜单块,该块集成在不包含菜单的一般布局中。例如,page2 如下所示:

{% extends "layout.html" %}
{% block menu %}
<li><a href="{% url 'myapp:index' %}">Home</a></li>
<li><a href="{% url 'myapp:page1' %}">page1</a></li>
<li class="active"><a href="{% url 'myapp:page2' %}">page2</a></li>
<li><a href="{% url 'myapp:page3' %}">page3</a></li>
{% endblock %}

问题在于,除了那个解决方案不太漂亮之外,每次我想向标题菜单添加链接时,我都必须修改我拥有的每一页。由于这远非最佳,我想知道你们中是否有人知道这样做的更好方法。

提前致谢!

【问题讨论】:

    标签: django navigation django-views django-templates


    【解决方案1】:

    您可以创建自定义模板标签:

    from django import template
    from django.core.urlresolvers import reverse, NoReverseMatch, resolve
    
    register = template.Library()
    
    @register.simple_tag
    def active(request, view_name):
        url = resolve(request.path)
        if url.view_name == view_name:
            return 'active'
        try:
            uri = reverse(view_name)
        except NoReverseMatch:
            uri = view_name
        if request.path.startswith(uri):
            return 'active'
        return ''
    

    并在模板中使用它来识别哪个页面是通过URL加载的

    <li class="{% active request 'car_edit' %}"><a href="{% url 'car_edit' car.pk %}">Edit</a></li>
    

    【讨论】:

      【解决方案2】:

      如果您在每个视图中都有一个“页面”对象,您可以将导航项的 slug 与对象的 slug 进行比较

      navigation.html

      <ul>
          {% for page in navigation %}
              <li{% ifequal object.slug page.slug %} class="active"{% endifequal %}>
                  <a href="{{ page.get_absolute_url }}">{{ page.title }}</a>
              </li>
          {% endfor %}
      </ul>
      

      base.html

      <html>
          <head />
          <body>
              {% include "navigation.html" %}
              {% block content %}
                  Welcome Earthling.
              {% endblock %}
          </body>
      </html>
      

      page.html

      {% extends "base.html" %}
      
      {% block content %}
          {{ object }}
      {% endblock %}
      

      其中导航可能是一个包含所有页面的context_processor 变量,而对象是当前的PageDetailView 对象变量

      免责声明

      如 Paulo 所述,您的问题有很多解决方案。当然这个解决方案假定每个视图都拥有一个页面对象,这个概念通常由CMS 实现。如果您的视图不是从 Page 应用派生的,则必须在导航中注入页面伪装者(至少包含 get_absolute_url 和 title 属性)。

      这可能是一个非常好的学习体验,但您可能会节省安装 feinCMS 或 django-cms 的负载时间,它们都定义了 ApplicationContent 原则。

      【讨论】:

      • 感谢您的帮助!如果我理解得很好,尽管这需要在每次调用视图时传递一个包含所有页面的navigation 变量?我想我可以将它存储在控制器中的一个位置,以便轻松修改。
      • 通常您使用context_processor 将变量传递给您的所有视图
      【解决方案3】:

      您可以使用include 标记并将其传递给当前页面的值。

      例如,这可能是一个单独的文件,仅用于声明菜单模板:

      menu.html

      {% if active = "a" %}
      <li><a href="{% url 'myapp:index' %}">Home</a></li>
      {% if active = "b" %}
      <li><a href="{% url 'myapp:page1' %}">page1</a></li>
      {% if active = "c" %}
      <li class="active"><a href="{% url 'myapp:page2' %}">page2</a></li>
      {% if active = "d" %}
      <li><a href="{% url 'myapp:page3' %}">page3</a></li>
      

      然后像这样在你的模板中调用它:

      {% include 'path/to/menu.html' with active="b"%} # or a or c or d.
      

      希望对你有帮助!

      【讨论】:

      • 这不是一个非常 DRY 的方法,但在极少数情况下它可能是一种选择
      • 为什么不干?他说每页都重复菜单让他很困扰。通过这种方式,您只需在一个模板中声明菜单。这就是干的定义!不要到处重复菜单。如果您需要进行一些修改,您只需更改菜单模板。它对我有用。
      • 是的,但您仍然在该模板中有很多 if 子句,而不是动态检查 active 的值
      • 关于很多ifs 你是对的,但是,我可以在我的内部使用你的解决方案,只传递navigation 列表,它会非常简单、漂亮、重构和干燥.我刚刚提供了一个我以前在菜单中使用过的快速解决方案。代码确实很丑,但很容易美化。我仍然更喜欢这个而不是在每个模板中重复菜单,但只是我自己。
      • 我的解决方案是编写一个模板并将所有用于呈现菜单的逻辑存储在那里。该模板将收到一个参数,您现在将使用该参数将哪个菜单标记为活动。您可以从需要包含具有适当参数的菜单的任何位置调用此模板。您只需将每个模板中的菜单文字替换为 include 标记。
      猜你喜欢
      • 2011-07-22
      • 2021-10-09
      • 1970-01-01
      • 1970-01-01
      • 2011-10-17
      • 1970-01-01
      • 2017-04-23
      • 1970-01-01
      • 2013-03-31
      相关资源
      最近更新 更多