模板继承

最后更新于:2022-04-01 04:04:03

Jinja 中最强大的部分就是模板继承。模板继承允许你构建一个包含你站点共同元素的基 本模板“骨架”,并定义子模板可以覆盖的 **块** 。 听起来复杂,实际上很简单。从例子上手是最易于理解的。 ### 基本模板[](http://docs.jinkan.org/docs/jinja2/templates.html#id11 "Permalink to this headline") 这个模板,我们会把它叫做 base.html ,定义了一个简单的 HTML 骨架文档,你可 能使用一个简单的两栏页面。用内容填充空的块是子模板的工作: ~~~ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html lang="en"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> {% block head %} <link rel="stylesheet" href="style.css" /> <title>{% block title %}{% endblock %} - My Webpage</title> {% endblock %} </head> <body> <div id="content">{% block content %}{% endblock %}</div> <div id="footer"> {% block footer %} &copy; Copyright 2008 by <a href="http://domain.invalid/">you</a>. {% endblock %} </div> </body> ~~~ 在本例中, {% block %} 标签定义了四个字幕版可以填充的块。所有的 block 标签 告诉模板引擎子模板可以覆盖模板中的这些部分。 ### 子模板[](http://docs.jinkan.org/docs/jinja2/templates.html#id12 "Permalink to this headline") 一个子模板看起来是这样: ~~~ {% extends "base.html" %} {% block title %}Index{% endblock %} {% block head %} {{ super() }} <style type="text/css"> .important { color: #336699; } </style> {% endblock %} {% block content %} <h1>Index</h1> <p class="important"> Welcome on my awesome homepage. </p> {% endblock %} ~~~ {% extend %} 标签是这里的关键。它告诉模板引擎这个模板“继承”另一个模板。 当模板系统对这个模板求值时,首先定位父模板。 extends 标签应该是模板中的第一个 标签。它前面的所有东西都会按照普通情况打印出来,而且可能会导致一些困惑。更多 该行为的细节以及如何利用它,见 [*Null-Master 退回*](http://docs.jinkan.org/docs/jinja2/tricks.html#null-master-fallback) 。 模板的文件名依赖于模板加载器。例如 FileSystemLoader 允许你用文件名访 问其它模板。你可以使用斜线访问子目录中的模板: ~~~ {% extends "layout/default.html" %} ~~~ 这种行为也可能依赖于应用内嵌的 Jinja 。注意子模板没有定义 footer 块,会 使用父模板中的值。 你不能在同一个模板中定义多个同名的 {% block %} 标签。因为块标签以两种 方向工作,所以存在这种限制。即一个块标签不仅提供一个可以填充的部分,也在父级 定义填充的内容。如果同一个模板中有两个同名的 {% blok %} 标签,父模板 无法获知要使用哪一个块的内容。 如果你想要多次打印一个块,无论如何你可以使用特殊的 self 变量并调用与块同名 的函数: ~~~ <title>{% block title %}{% endblock %}</title> <h1>{{ self.title() }}</h1> {% block body %}{% endblock %} ~~~ ### Super 块[](http://docs.jinkan.org/docs/jinja2/templates.html#super "Permalink to this headline") 可以调用 super 来渲染父级块的内容。这会返回父级块的结果: ~~~ {% block sidebar %} <h3>Table Of Contents</h3> ... {{ super() }} {% endblock %} ~~~ ### 命名块结束标签[](http://docs.jinkan.org/docs/jinja2/templates.html#id13 "Permalink to this headline") Jinja2 允许你在块的结束标签中加入的名称来改善可读性: ~~~ {% block sidebar %} {% block inner_sidebar %} ... {% endblock inner_sidebar %} {% endblock sidebar %} ~~~ 无论如何, endblock 后面的名称一定与块名匹配。 ### 嵌套块和作用域[](http://docs.jinkan.org/docs/jinja2/templates.html#id14 "Permalink to this headline") 嵌套块可以胜任更复杂的布局。而默认的块不允许访问块外作用域中的变量: ~~~ {% for item in seq %} <li>{% block loop_item %}{{ item }}{% endblock %}</li> {% endfor %} ~~~ 这个例子会输出空的  项,因为 item 在块中是不可用的。其原因是,如果 块被子模板替换,变量在其块中可能是未定义的或未被传递到上下文。 从 Jinja 2.2 开始,你可以显式地指定在块中可用的变量,只需在块声明中添加 scoped 修饰,就把块设定到作用域中: ~~~ {% for item in seq %} <li>{% block loop_item scoped %}{{ item }}{% endblock %}</li> {% endfor %} ~~~ 当覆盖一个块时,不需要提供 scoped 修饰。 ### 模板对象[](http://docs.jinkan.org/docs/jinja2/templates.html#id15 "Permalink to this headline") Changed in version 2.4. 当一个模板对象被传递到模板上下文,你也可以从那个对象继承。假设调用 代码传递layout_template 布局模板到环境,这段代码会工作: ~~~ {% extends layout_template %} ~~~ 之前 layout_template 变量一定是布局模板文件名的字符串才能工作。
';