jinja2模板设计五:导入、上下文、表达式、运算符
导入
Jinja2 支持在宏中放置经常使用的代码。这些宏可以被导入,并不同的模板中使用。
这 与 Python 中的 import 语句类似。要知道的是,导入量会被缓存,并且默认下导入的 模板不能访问当前模板中的非全局变量。更多关于导入和包含的上下文行为见 导入上下文行为 。
有两种方式来导入模板。你可以把整个模板导入到一个变量或从其中导入请求特定的宏 /导出量。
比如我们有一个渲染表单(名为 forms.html )的助手模块:
{% macro input(name, value='', type='text') -%}
<input type="{{ type }}" value="{{ value|e }}" name="{{ name }}">
{%- endmacro %}
{%- macro textarea(name, value='', rows=10, cols=40) -%}
<textarea name="{{ name }}" rows="{{ rows }}" cols="{{ cols
}}">{{ value|e }}</textarea>
{%- endmacro %}
最简单灵活的方式是把整个模块导入为一个变量。这样你可以访问属性:
{% import 'forms.html' as forms %}
<dl>
<dt>Username</dt>
<dd>{{ forms.input('username') }}</dd>
<dt>Password</dt>
<dd>{{ forms.input('password', type='password') }}</dd>
</dl>
<p>{{ forms.textarea('comment') }}</p>
此外你也可以从模板中导入名称到当前的命名空间:
{% from 'forms.html' import input as input_field, textarea %}
<dl>
<dt>Username</dt>
<dd>{{ input_field('username') }}</dd>
<dt>Password</dt>
<dd>{{ input_field('password', type='password') }}</dd>
</dl>
<p>{{ textarea('comment') }}</p>
名称以一个或更多下划线开始的宏和变量是私有的,不能被导入。
Changed in version 2.4: 如果传递一个模板对象到模板上下文,从那个对象中导入。
导入上下文行为
默认下,每个包含的模板会被传递到当前上下文,而导入的模板不会。这样做的原因 是导入量不会像包含量被缓存,因为导入量经常只作容纳宏的模块。
无论如何,这当然也可以显式地更改。通过在 import/include 声明中直接添加 with context 或 without context ,当前的上下文可以传递到模板,而且不会 自动禁用缓存。
这里有两个例子:
{% from 'forms.html' import input with context %}
{% include 'header.html' without context %}
提示
在 Jinja 2.0 中,被传递到被包含模板的上下文不包含模板中定义的变量。 事实上,这不能工作:
{% for box in boxes %}
{% include "render_box.html" %}
{% endfor %}
在 Jinja 2.0 中,被包含的模板 render_box.html 不能 访问 box 。从 Jinja 2.1 开始, render_box.html 可以 这么做。
表达式
Jinja 中到处都允许使用基本表达式。这像常规的 Python 一样工作,即使你不用 Python 工作,你也会感受到其带来的便利。
字面量
表达式最简单的形式就是字面量。字面量表示诸如字符串和数值的 Python 对象。下面 的字面量是可用的:
- “Hello World”:
- 双引号或单引号中间的一切都是字符串。无论何时你需要在模板中使用一个字 符串(比如函数调用、过滤器或只是包含或继承一个模板的参数),它们都是 有用的。
- 42 / 42.23:
- 直接写下数值就可以创建整数和浮点数。如果有小数点,则为浮点数,否则为 整数。记住在 Python 里, 42 和 42.0 是不一样的。
- [‘list’, ‘of’, ‘objects’]:
-
一对中括号括起来的东西是一个列表。列表用于存储和迭代序列化的数据。例如 你可以容易地在 for 循环中用列表和元组创建一个链接的列表:
<ul> {% for href, caption in [('index.html', 'Index'), ('about.html', 'About'), ('downloads.html', 'Downloads')] %} <li><a href="{{ href }}">{{ caption }}</a></li> {% endfor %} </ul>
- (‘tuple’, ‘of’, ‘values’):
- 元组与列表类似,只是你不能修改元组。如果元组中只有一个项,你需要以逗号 结尾它。元组通常用于表示两个或更多元素的项。更多细节见上面的例子。
- {‘dict’: ‘of’, ‘key’: ‘and’, ‘value’: ‘pairs’}:
- Python 中的字典是一种关联键和值的结构。键必须是唯一的,并且键必须只有一个 值。字典在模板中很少使用,罕用于诸如 xmlattr() 过滤器之类。
- true / false:
- true 永远是 true ,而 false 始终是 false 。
提示
特殊常量 true 、 false 和 none 实际上是小写的。因为这在过去会导致 混淆,过去 True扩展为一个被认为是 false 的未定义的变量。所有的这三个 常量也可以被写成首字母大写( True 、 False 和 None )。尽管如此, 为了一致性(所有的 Jinja 标识符是小写的),你应该使用小写的版本。
算术
Jinja 允许你用计算值。这在模板中很少用到,但是为了完整性允许其存在。支持下面的 运算符:
- +
- 把两个对象加到一起。通常对象是素质,但是如果两者是字符串或列表,你可以用这 种方式来衔接它们。无论如何这不是首选的连接字符串的方式!连接字符串见 ~ 运算符。 {{ 1 + 1 }} 等于 2 。
- -
- 用第一个数减去第二个数。 {{ 3 - 2 }} 等于 1 。
- /
- 对两个数做除法。返回值会是一个浮点数。 {{ 1 / 2 }} 等于 {{ 0.5 }} 。
- //
- 对两个数做除法,返回整数商。 {{ 20 // 7 }} 等于 2 。
- %
- 计算整数除法的余数。 {{ 11 % 7 }} 等于 4 。
- *
- 用右边的数乘左边的操作数。 {{ 2 * 2 }} 会返回 4 。也可以用于重 复一个字符串多次。 {{ ‘=’ * 80 }} 会打印 80 个等号的横条。
- **
- 取左操作数的右操作数次幂。 {{ 2**3 }} 会返回 8 。
比较
- ==
- 比较两个对象是否相等。
- !=
- 比较两个对象是否不等。
- >
- 如果左边大于右边,返回 true 。
- >=
- 如果左边大于等于右边,返回 true 。
- <
- 如果左边小于右边,返回 true 。
- <=
- 如果左边小于等于右边,返回 true 。
逻辑
对于 if 语句,在 for 过滤或 if 表达式中,它可以用于联合多个表达式:
- and
- 如果左操作数和右操作数同为真,返回 true 。
- or
- 如果左操作数和右操作数有一个为真,返回 true 。
- not
- 对一个表达式取反(见下)。
- (expr)
- 表达式组。
提示
is 和 in 运算符同样支持使用中缀记法: foo is not bar 和 foo not in bar 而不是 not foois bar 和 not foo in bar 。所有的 其它表达式需要前缀记法 not (foo and bar) 。
其它运算符
下面的运算符非常有用,但不适用于其它的两个分类:
- ~
- 把所有的操作数转换为字符串,并且连接它们。 {{ "Hello " ~ name ~ "!" }} 会返回(假设 name 值为 ''John' ) Hello John! 。
- ()
- 调用一个可调用量:{{ post.render() }} 。在圆括号中,你可以像在 python 中一样使用位置参数和关键字参数: {{ post.render(user, full=true) }} 。
- . / []
- 获取一个对象的属性。(见 变量 )
If 表达式
同样,也可以使用内联的 if 表达式。这在某些情况很有用。例如你可以用来在一个 变量定义的情况下才继承一个模板,否则继承默认的布局模板:
{% extends layout_template if layout_template is defined else 'master.html' %}
一般的语法是 <do something> if <something is true> else <do something else> 。
else 部分是可选的。如果没有显式地提供 else 块,会求值一个未定义对象:
{{ '[%s]' % page.title if page.title }}
posted on 2015-08-05 17:31 myworldworld 阅读(1046) 评论(0) 收藏 举报