模板设计者文档

您所在的位置:网站首页 jinja2渲染 模板设计者文档

模板设计者文档

2023-03-08 01:44| 来源: 网络整理| 查看: 265

模板设计者文档¶

这份文档描述了模板引擎中的语法和语义结构,对于创建 Jinja 模板是一份相当有用 的参考。因为模板引擎非常灵活,应用中的配置会在分隔符和未定义值的行为方面与 这里的配置有细微差异。

概要¶

模板仅仅是文本文件。它可以生成任何基于文本的格式(HTML、XML、CSV、LaTex 等等)。 它并没有特定的扩展名, .html 或 .xml 都是可以的。

模板包含 变量 或 表达式 ,这两者在模板求值的时候会被替换为值。模板中 还有标签,控制模板的逻辑。模板语法的大量灵感来自于 Django 和 Python 。

下面是一个最小的模板,它阐明了一些基础。我们会在文档中后面的部分解释细节:

My Webpage {% for item in navigation %} {{ item.caption }} {% endfor %} My Webpage {{ a_variable }}

这包含了默认的设定。应用开发者也会把语法从 {% foo %} 改成 或类似的东西。

这里有两种分隔符: {% ... %} 和 {{ ... }} 。前者用于执行诸如 for 循环 或赋值的语句,后者把表达式的结果打印到模板上。

变量¶

应用把变量传递到模板,你可能在模板中弄混。变量上面也可以有你能访问的属性或元 素。变量看起来是什么,完全取决于应用提供了什么。

你可以使用点( . )来访问变量的属性,作为替代,也可以使用所谓的“下标”语 法( [] )。下面的几行效果是一样的:

{{ foo.bar }} {{ foo['bar'] }}

知晓花括号 不是 变量的一部分,而是打印语句的一部分是重要的。如果你访问标签 里的不带括号的变量。

如果变量或属性不存在,会返回一个未定义值。你可以对这类值做什么取决于应用的配 置,默认的行为是它如果被打印,其求值为一个空字符串,并且你可以迭代它,但其它 操作会失败。

实现

为方便起见,Jinja2 中 foo.bar 在 Python 层中做下面的事情:

检查 foo 上是否有一个名为 bar 的属性。 如果没有,检查 foo 中是否有一个 'bar' 项 。 如果没有,返回一个未定义对象。

foo['bar'] 的方式相反,只在顺序上有细小差异:

检查在 foo 中是否有一个 'bar' 项。 如果没有,检查 foo 上是否有一个名为 bar 的属性。 如果没有,返回一个未定义对象。

如果一个对象有同名的项和属性,这很重要。此外,有一个 attr() 过滤 器,它只查找属性。

过滤器¶

变量可以通过 过滤器 修改。过滤器与变量用管道符号( | )分割,并且也 可以用圆括号传递可选参数。多个过滤器可以链式调用,前一个过滤器的输出会被作为 后一个过滤器的输入。

例如 {{ name|striptags|title }} 会移除 name 中的所有 HTML 标签并且改写 为标题样式的大小写格式。过滤器接受带圆括号的参数,如同函数调用。这个例子会 把一个列表用逗号连接起来: {{ list|join(', ') }} 。

下面的 内置过滤器清单 节介绍了所有的内置过滤器。

测试¶

除了过滤器,所谓的“测试”也是可用的。测试可以用于对照普通表达式测试一个变量。 要测试一个变量或表达式,你要在变量后加上一个 is 以及测试的名称。例如,要得出 一个值是否定义过,你可以用 name is defined ,这会根据 name 是否定义返回 true 或 false 。

测试也可以接受参数。如果测试只接受一个参数,你可以省去括号来分组它们。例如, 下面的两个表达式做同样的事情:

{% if loop.index is divisibleby 3 %} {% if loop.index is divisibleby(3) %}

下面的 内置测试清单 章节介绍了所有的内置测试。

注释¶

要把模板中一行的部分注释掉,默认使用 {# ... #} 注释语法。这在调试或 添加给你自己或其它模板设计者的信息时是有用的:

{# note: disabled template because we no longer use this {% for user in users %} ... {% endfor %} #} 空白控制¶

默认配置中,模板引擎不会对空白做进一步修改,所以每个空白(空格、制表符、换行符 等等)都会原封不动返回。如果应用配置了 Jinja 的 trim_blocks ,模板标签后的 第一个换行符会被自动移除(像 PHP 中一样)。

此外,你也可以手动剥离模板中的空白。当你在块(比如一个 for 标签、一段注释或变 量表达式)的开始或结束放置一个减号( - ),可以移除块前或块后的空白:

{% for item in seq -%} {{ item }} {%- endfor %}

这会产出中间不带空白的所有元素。如果 seq 是 1 到 9 的数字的列表, 输出会是 123456789 。

如果开启了 行语句 ,它们会自动去除行首的空白。

提示

标签和减号之间不能有空白。

有效的:

{%- if foo -%}...{% endif %}

无效的:

{% - if foo - %}...{% endif %} 转义¶

有时想要或甚至必要让 Jinja 忽略部分,不会把它作为变量或块来处理。例如,如果 使用默认语法,你想在在使用把 {{ 作为原始字符串使用,并且不会开始一个变量 的语法结构,你需要使用一个技巧。

最简单的方法是在变量分隔符中( {{ )使用变量表达式输出:

{{ '{{' }}

对于较大的段落,标记一个块为 raw 是有意义的。例如展示 Jinja 语法的实例, 你可以在模板中用这个片段:

{% raw %} {% for item in seq %} {{ item }} {% endfor %} {% endraw %} 行语句¶

如果应用启用了行语句,就可以把一个行标记为一个语句。例如如果行语句前缀配置为 # ,下面的两个例子是等价的:

# for item in seq {{ item }} # endfor {% for item in seq %} {{ item }} {% endfor %}

行语句前缀可以出现在一行的任意位置,只要它前面没有文本。为了语句有更好的可读 性,在块的开始(比如 for 、 if 、 elif 等等)以冒号结尾:

# for item in seq: ... # endfor

提示

若有未闭合的圆括号、花括号或方括号,行语句可以跨越多行:

# for href, caption in [('index.html', 'Index'), ('about.html', 'About')]: {{ caption }} # endfor

从 Jinja 2.2 开始,行注释也可以使用了。例如如果配置 ## 为行注释前缀, 行中所有 ## 之后的内容(不包括换行符)会被忽略:

# for item in seq: {{ item }} ## this comment is ignored # endfor 模板继承¶

Jinja 中最强大的部分就是模板继承。模板继承允许你构建一个包含你站点共同元素的基 本模板“骨架”,并定义子模板可以覆盖的 块 。

听起来复杂,实际上很简单。从例子上手是最易于理解的。

基本模板¶

这个模板,我们会把它叫做 base.html ,定义了一个简单的 HTML 骨架文档,你可 能使用一个简单的两栏页面。用内容填充空的块是子模板的工作:

{% block head %} {% block title %}{% endblock %} - My Webpage {% endblock %} {% block content %}{% endblock %} {% block footer %} © Copyright 2008 by you. {% endblock %}

在本例中, {% block %} 标签定义了四个字幕版可以填充的块。所有的 block 标签 告诉模板引擎子模板可以覆盖模板中的这些部分。

子模板¶

一个子模板看起来是这样:

{% extends "base.html" %} {% block title %}Index{% endblock %} {% block head %} {{ super() }} .important { color: #336699; } {% endblock %} {% block content %} Index Welcome on my awesome homepage.

{% endblock %}

{% extend %} 标签是这里的关键。它告诉模板引擎这个模板“继承”另一个模板。 当模板系统对这个模板求值时,首先定位父模板。 extends 标签应该是模板中的第一个 标签。它前面的所有东西都会按照普通情况打印出来,而且可能会导致一些困惑。更多 该行为的细节以及如何利用它,见 Null-Master 退回 。

模板的文件名依赖于模板加载器。例如 FileSystemLoader 允许你用文件名访 问其它模板。你可以使用斜线访问子目录中的模板:

{% extends "layout/default.html" %}

这种行为也可能依赖于应用内嵌的 Jinja 。注意子模板没有定义 footer 块,会 使用父模板中的值。

你不能在同一个模板中定义多个同名的 {% block %} 标签。因为块标签以两种 方向工作,所以存在这种限制。即一个块标签不仅提供一个可以填充的部分,也在父级 定义填充的内容。如果同一个模板中有两个同名的 {% blok %} 标签,父模板 无法获知要使用哪一个块的内容。

如果你想要多次打印一个块,无论如何你可以使用特殊的 self 变量并调用与块同名 的函数:

{% block title %}{% endblock %} {{ self.title() }} {% block body %}{% endblock %} Super 块¶

可以调用 super 来渲染父级块的内容。这会返回父级块的结果:

{% block sidebar %} Table Of Contents ... {{ super() }} {% endblock %} 命名块结束标签¶

Jinja2 允许你在块的结束标签中加入的名称来改善可读性:

{% block sidebar %} {% block inner_sidebar %} ... {% endblock inner_sidebar %} {% endblock sidebar %}

无论如何, endblock 后面的名称一定与块名匹配。

嵌套块和作用域¶

嵌套块可以胜任更复杂的布局。而默认的块不允许访问块外作用域中的变量:

{% for item in seq %} {% block loop_item %}{{ item }}{% endblock %} {% endfor %}

这个例子会输出空的 项,因为 item 在块中是不可用的。其原因是,如果 块被子模板替换,变量在其块中可能是未定义的或未被传递到上下文。

从 Jinja 2.2 开始,你可以显式地指定在块中可用的变量,只需在块声明中添加 scoped 修饰,就把块设定到作用域中:

{% for item in seq %} {% block loop_item scoped %}{{ item }}{% endblock %} {% endfor %}

当覆盖一个块时,不需要提供 scoped 修饰。

模板对象¶

Changed in version 2.4.

当一个模板对象被传递到模板上下文,你也可以从那个对象继承。假设调用 代码传递 layout_template 布局模板到环境,这段代码会工作:

{% extends layout_template %}

之前 layout_template 变量一定是布局模板文件名的字符串才能工作。

HTML 转义¶

当从模板生成 HTML 时,始终有这样的风险:变量包含影响已生成 HTML 的字符。有两种 解决方法:手动转义每个字符或默认自动转义所有的东西。

Jinja 两者都支持,使用哪个取决于应用的配置。默认的配置未开启自动转义有这样几个 原因:

转义所有非安全值的东西也意味着 Jijna 转义已知不包含 HTML 的值,比如数字,对 性能有巨大影响。 关于变量安全性的信息是易碎的。可能会发生强制标记一个值为安全或非安全的情况, 而返回值会被作为 HTML 转义两次。 使用手动转义¶

如果启用了手动转义,按需转义变量就是 你的 责任。要转义什么?如果你有 一个 可能 包含 > 、



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3