模版
NGraphX 使用 Jinja 模版引擎支持提示词等文本动态构建。模版的值大多来源于远程流程调用传递的参数。
模板设计者指南
本指南深入解析了模板引擎的语法规则和内在含义,对于致力于构建 Jinja 模板的开发者而言,它无疑是一份不可或缺的参考资料。
模板由变量、表达式组成,渲染时会被值替换;还包含控制逻辑的标签。其语法类似于Python。
以下是一个基本的模板示例:
<!DOCTYPE html>
<html lang="en">
<head>
<title>我的网页</title>
</head>
<body>
<ul id="navigation">
{% for item in navigation %}
<li><a href="{{ item.href }}">{{ item.caption }}</a></li>
{% endfor %}
</ul>
<h1>我的网页</h1>
{{ a_variable }}
</body>
</html>
Jinja 有几种定界符:
{% ... %}
用于语句{{ ... }}
用于表达式输出{# ... #}
用于注释
变量
变量是一个存储数据的容器,可以是任 何类型。变量通过 {{ ... }}
语法访问。
{{ my_variable }}
你可以使用点号 (.) 来访问变量的属性,就像使用 Python 的标准 getitem “下标”语法 ([]) 一样。
以下两行代码具有相同的效果:
{{ foo.bar }}
{{ foo['bar'] }}
如果变量或属性不存在,在模版渲染之时会返回空字符串。
表达式
表达式是 Jinja 模板中最重要的部分,它用于输出变量的值。表达式语法与 Python 类似,支持运算符、函数、过滤器等。
{{ my_variable + 1 }}
字面量
最简单的表达式形式是字面量。字面量是Python对象的表示,例如字符串和数字。以下是几种常见的字面量类型:
- 字符串:用双引号或单引号括起来的内容都是字符串,例如 "Hello World"。在模板中,字符串非常有用,比如作为函数调用和过滤器的参数。
- 整数:没有小数部分的整数值。可以使用下划线“_”来分隔数字组以提高可读性,例如 42 / 123_456。
- 浮点数:使用小数点“.”作为小数点符号的数值。它们也可以用科学记数法表示,即使用大写或小写的“e”来表示指数部分。同样可以使用下划线分隔数字组,但不可用于指数部分,例如 42.23 / 42.1e2 / 123_456.789。
- 列表:用方括号“[]”包围的内容是列表。列表适用于存储需要遍历的顺序数据。例如,可以使用列表和元组在for循环中创建链接列表:
<ul>
{% for href, caption in [('index.html', 'Index'), ('about.html', 'About'),
('downloads.html', 'Downloads')] %}
<li><a href="{{ href }}">{{ caption }}</a></li>
{% endfor %}
</ul>
- 元组:与列表类似,但不可修改(即“不可变”)。如果元组只有一个元素,则必须用逗号括起来(例如 ('1-tuple',))。元组通常用于表示两个或多个元素的项。在上面的列表示例中可以看到更多细节。
- 字典:Python中的字典是一种将键与值关联的结构。键必须是唯一的,并且每个键都恰好有一个值。在模板中,字典的使用相对较少,但在某些情况下(例如xmlattr()过滤器)非常有用。
- 布尔值:true表示真,false表示假。
特殊常量true、false和none实际上是小写字母的。由于过去曾经引起过混淆(True曾扩展到一个未定义的变量,被认为是假的),现在这三个常量也可以写成大写形式(True, False, None)。然而,为了保持一致性,所有Jinja标识符都应使用小写版本。
数学运算
Jinja 支持以下数学运算符:
+
:加法-
:减法/
:除法//
:地板除法%
:取模*
:乘法**
:幂运算
比较运算
Jinja 支持以下比较运算符:
==
:等于!=
:不等于>
:大于<
:小于>=
:大于等于<=
:小于等于
逻辑运算
Jinja 支持以下逻辑运算符:
and
:逻辑与or
:逻辑或not
:逻辑非
其他操作符
Jinja 还支持一些其他操作符,如 in
、is
、|
、~
、()
、. / []
。
in
执行序列/映射包含测试。如果左操作数在右操作数中,则返回true。例如,{{ 1 in [1, 2, 3] }}
会返回true。is
执行一个测试。|
(管道符) 应用过滤器。~
(波浪号) 将所有操作数转换为字符串并连接它们。例如,如果name
被设置为'John',则{{ "Hello " ~ name ~ "!"}}
会返回"Hello John!"。()
调用一个可调用对象:{{ post.render() }}
。在括号内,您可以像Python中一样使用位置参数和关键字参数:{{ post.render(user, full=true) }}
。. / []
获取对象的属性。(参见变量)
这些操作符在日常使用中非常有用。
内置过滤器
过滤器用于修改表达式的输出。过滤器通过管道符号 |
应用,可以链式调用。
{{ my_variable|upper }}
方法名称 | 参数 | 使用说明 |
---|---|---|
abs() | value | 返回给定数字的绝对值。 |
forceescape() | value | 强制转义字符串中的特殊字符。 |
map() | function, iterable | 应用一个函数到可迭代对象的每个元素上,并返回结果列表。 |
select() | expression | 选择特定条件下的记录。 |
unique() | iterable | 返回唯一元素组成的序列。 |
attr() | obj, attribute | 获取对象的指定属性值。 |
format() | template, args | 格式化输出字符串,其中 template 是格式化模板,args 是传递给模板的参数字典。 |
max() | iterable | 返回给定可迭代对象中的最大值。 |
selectattr() | obj, attribute, expression | 根据对象的特定属性选择记录。 |
upper() | value | 将字符串转换为大写。 |
batch() | page, per_page | 分批处理数据,显示指定页码和每页的条目数。 |
groupby() | iterable, [key_func] | 按照键函数对可迭代对象进行分组。 |
min() | iterable | 返回给定可迭代对象中的最小值。 |
slice() | start, stop, [step] | 切片序列,可选的步长参数默认为1。 |
urlencode() | value | 将字符串编码为URL编码格式。 |
capitalize() | value | 将字符串的首字母转换为大写,其余转换为小写。 |
indent() | value, num | 在字符串前添加指定数量的空格缩进。 |
pprint() | obj | 打印一个对象,使其可读性更好。 |
sort() | iterable, [cmp_func] | 对序列进行排序,可选的比较函数用于自定义排序规则。 |
urlize() | value | 将URL转换为点击链接。 |
center() | value: str, width: int = 80 | 居中字符串,宽度默认为80个字符。 |
int() | value | 将值转换为整数。 |
random() | [seed] | 返回一个随机数,可选的种子参数用于生成可预测的结果。 |
string() | obj | 将任何类型的对象转换为字符串。 |
wordcount() | value | 计算字符串中的单词数量。 |
default() | expression, default_value | 如果表达式为None或False,则返回默认值。 |
items() | dictionary | 返回字典的项列表。 |
reject() | iterable, expression | 从可迭代对象中排除满足条件的元素。 |
striptags() | value | 移除字符串中的HTML标签。 |
wordwrap() | value, width: int = 0 | 将长字符串包装成多行文本,宽度默认为0(自动计算)。 |
dictsort() | dictionary, [key_func] | 对字典进行排序,可选的键函数用于自定义排序规则。 |
join() | iterable, delimiter: str = '' | 使用分隔符连接可迭代对象中的元素。 |
rejectattr() | iterable, attribute, expression | 从可迭代对象中排除具有特定属性的记录。 |
sum() | iterable | 计算可迭代对象中的所有数值之和。 |
xmlattr() | obj, attribute | 获得对象的指定属性值,通常用于生成XML输出。 |
escape() | value | 将字符串转义以安全地嵌入到HTML中。 |
last() | iterable | 返回序列的最后一个元素。 |
replace() | value, from_, to_ | 替换字符串中的旧值为新值。 |
title() | value | 将字符串转换为标题格式(每个单词首字母大写)。 |
filesizeformat() | value | 将字节数格化为易读的文件大小格式。 |
length() | iterable | 返回序列的长度。 |
reverse() | iterable | 返回序列的逆序副本。 |
tojson() | obj | 将对象转换为JSON字符串。 |
first() | iterable | 返回序列的第一个元素。 |
list() | iterable | 将可迭代对象转换为列表。 |
round() | value, ndigits: int = None | 四舍五入数字到指定的小数位数。 |
float() | value | 将值转换为浮点数。 |
lower() | value | 将字符串转换为小写。 |
safe() | value | 确保字符串是安全的,即不会产生HTML注入。 |
控制逻辑
Jinja 支持多种控制逻辑,如 if
、for
、block
等。控制逻辑通过 {% ... %}
语法实现。
{% block content %}
<h1>My Webpage</h1>
<p>Content goes here.</p>
{% endblock %}
{% if my_variable > 0 %}
{{ my_variable }} 是正数
{% else %}
{{ my_variable }} 是负数
{% endif %}
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% else %}
<li><em>no users found</em></li>
{% endfor %}
</ul>
<dl>
{% for key, value in my_dict | dictsort %}
<dt>{{ key|e }}</dt>
<dd>{{ value|e }}</dd>
{% endfor %}
</dl>
循环块中特别的值:
变量 | 描述 |
---|---|
loop.index | 循环当前迭代的索引。索引从1开 始计数 |
loop.index0 | 循环当前迭代的索引。索引从0开始计数 |
loop.revindex | 从循环末尾算起,剩余的迭代次数。索引从1开始计数 |
loop.revindex0 | 从循环末尾算起,剩余的迭代次数。索引从0开始计数 |
loop.first | 如果是第一次迭代,则为真 |
loop.last | 如果是最后一次迭代,则为真 |
loop.length | 循环中项目的总数 |
loop.cycle | 一个辅助函数,用于在一系列序列之间循环。具体说明请见下文 |
loop.depth | 指示当前渲染处于递归循环的哪一层。起始值为1 |
loop.depth0 | 指示当前渲染处于递归循环的哪一层。起始值为0 |
loop.previtem | 上一个迭代中的项目。第一次迭代时为未定义 |
loop.nextitem | 下一个迭代中的项目。最后一次迭代时为未定义 |
loop.changed(*val) | 如果之前调用过且值不同(或从未调用过),则为真 |
{% for row in rows %}
<li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
{% endfor %}
loop.cycle
函数允许在多个序列之间进行循环,这在处理重复的列表项或在特定条件下切换不同的数据集时非常有用。具体用法和参数请参考相关文档或代码示例。
内置函数
Jinja 提供了一些内置函数,用于处理数据。例如,range()
函数用于生成一个整数序列。
{% for i in range(10) %}
{{ i }}
{% endfor %}
内置流程变量
变量名 | 类型 | 描述 |
---|---|---|
message | string | 用户最后一次的提问 |
data | List[Any] | 流程节点运行完成后绑定的数据集合 |
变量数据结构
message
Excel 中A1,B1求和
data
[
{
...
},
"",
...
]