版权声明
本文出自 “ 幻冥极地 ” 博客 ,作者 小貘 采用 署名-非商业性使用-相同方式共享 协议。转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。
https://www.moorehy.com/archives/224
Macros
宏(Macros)与常规编程语言中的函数相同。宏可用于将经常使用的代码放到一个可复用的函数中,从而实现不重复造轮子(“DRY”)。
下面是一个宏的小例子,它渲染了一个表单元素:
1 2 3 4 |
{% macro input(name, value='', type='text', size=20) -%} <input type="{{ type }}" name="{{ name }}" value="{{ value|e }}" size="{{ size }}"> {%- endmacro %} |
在其命名空间中,宏可以像一个函数那样被调用:
1 2 |
{{ input('username') }} {{ input('password', type='password') }} |
如果宏被定义在不同的模板中,您需要首先 import 。
在宏内部,您可以访问三个特殊的变量:
- varargs
- 如果传递给宏多余其接受的位置参数数量,那么这些多余的参数将作为值列表存在于一个特殊的 varargs 变量中。
- kwargs
- 像 varargs 一样,不过是对于关键字参数。所有未消费的关键字参数存储在这个特殊变量中。
- caller
- 如果一个宏从一个 call 标签中被调用,调用者(caller)作为可调用的宏被存储在这个变量中。
宏还暴露了一些其内部细节。以下属性可用于宏对象:
- name
- 宏名。 {{ input.name }} 将打印出 input 。
- arguments
- 宏接受的参数名称的元组。
- defaults
- 默认值的元组
- catch_kwargs
- 如果宏接受额外的关键字参数,则此值为 true (即:访问特别的 kwargs 变量)。
- catch_varargs
- 如果宏接受额外的位置参数,则此值为 true (即:访问特别的 varargs 变量)。
- caller
- 如果宏访问特别的 caller 变量,并且可以从 call 标签调用,则此值为 true 。
如果宏名以下划线开头,则为不可导出也不能被导入。
Call
在某些情况下,将宏传递给另一个宏是很有用的。为此,您可以使用特殊的 call 语句块。以下示例显示了利用 call 功能以及如何使用宏:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{% macro render_dialog(title, class='dialog') -%} <div class="{{ class }}"> <h2>{{ title }}</h2> <div class="contents"> {{ caller() }} </div> </div> {%- endmacro %} {% call render_dialog('Hello World') %} This is a simple dialog rendered by using a macro and a call block. {% endcall %} |
它也可以将参数传递回 call 语句块。这使得它可以作为循环(loops)的替代。一般来说, call 语句块完全像一个没有名称的宏。
下面是一个 call 语句块如何与参数一起使用的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
{% macro dump_users(users) -%} <ul> {%- for user in users %} <li>{{ user.username|e }}</p>{{ caller(user) }}</li> {%- endfor %} </ul> {%- endmacro %} {% call(user) dump_users(list_of_user) %} <dl> <dt>Realname</dt> <dd>{{ user.realname|e }}</dd> <dt>Description</dt> <dd>{{ user.description }}</dd> </dl> {% endcall %} |
Filters
过滤器块(sections)允许您在模板数据块上应用常规的 Jinja2 过滤器。只需要将代码封装在一个特殊的 filter 块(section)中:
1 2 3 |
{% filter upper %} This text becomes uppercase {% endfilter %} |
Assignments
在代码块内部,您还可以将值赋给变量。在顶层(代码块、宏或循环之外)的赋值可以从模板中导出,像顶层的宏,并且可被其他模板导入。
赋值使用 set 标签,并且可以有多个目标值:
1 2 |
{% set navigation = [('index.html', 'Index'), ('about.html', 'About')] %} {% set key, value = call_something() %} |
作用域行为
请记住,不可能在语句块外部使用语句块内部中设置(set)的变量。这也适用于循环(loops)。该规则的唯一例外是不会引入作用域的 if 语句。因此,以下模板不会像您期望的那样执行:
1 2 3 4 5 6 |
{% set iterated = false %} {% for item in seq %} {{ item }} {% set iterated = true %} {% endfor %} {% if not iterated %} did not iterate {% endif %} |
使用 Jinja 语法不可能做到这一点。但是您可以使用替代的结构,如循环的 else 语句块或者特殊的 loop 变量:
1 2 3 4 5 |
{% for item in seq %} {{ item }} {% else %} did not iterate {% endfor %} |
[…] 赋值 […]