技巧与窍门

这部分文档展示 Jinja 模板的一些技巧和窍门。

Null-Master Fallback

Jinja 支持动态继承,并且不区分父模板和子模板,只要没有访问 extends 标记。 虽然这会导致令人惊讶的行为,即第一个 extends 标记之前包括空白在内的所有内容都打印出来而不是被忽略,但它可用于巧妙的技巧。

通常,子模板从一个基本 HTML 骨架模板扩展。 但是,如果 standalone 变量计算为假,则可将 extends 标记放入 if 标记中,以便仅从布局模板扩展该标记,如果未定义则它按默认值执行该标记。 此外,一个非常基本的骨架被添加到文件中,以便如果它确实使用 standalone 设置为True渲染,则添加非常基本的 HTML 骨架:

{% if not standalone %}{% extends 'master.html' %}{% endif -%}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<title>{% block title %}The Page Title{% endblock %}</title>
<link rel="stylesheet" href="style.css" type="text/css">
{% block body %}
  <p>This is the page body.</p>
{% endblock %}

交替行

如果要对表或列表的每一行使用不同的样式,则可以在 loop 对象上使用 cycle 方法:

<ul>
{% for row in rows %}
  <li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
{% endfor %}
</ul>

cycle 可以接受无限的字符串。 每次遇到此标记时,都会渲染列表中的下一个项。

突出显示活动菜单项

通常,你希望有一个带有活动导航项的导航栏。 这非常简单。 由于子模板中 block 之外的赋值是全局的,并且在计算布局模板之前执行,因此可以在子模板中定义活动菜单项:

{% 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>
...

访问父循环

特殊 loop 变量始终指向最里面的循环。 如果希望访问外部循环,则可以对其取一个别名:

<table>
{% for row in table %}
  <tr>
  {% set rowloop = loop %}
  {% for cell in row %}
    <td id="cell-{{ rowloop.index }}-{{ loop.index }}">{{ cell }}</td>
  {% endfor %}
  </tr>
{% endfor %}
</table>