Ansible jinja2 模版


Jinj2 模版

一、Jinja2 基础知识

1.1 Jinja2 是什么?

Jinja2 一个基于 Python 开发的通用模板语言,它具有 灵活快速安全 等特性

1.2 Jinja2 模版是做什么呢?

以 ansible 为例,基于 jinja2 模版我们可以实现更丰富更灵活的文件配置

例如:我们希望让 redis 服务监听在本地非回环地址上,如下所示:

bind 192.168.10.120

可每个节点地址都不同,我们该如何做呢?

答案是 ansible facts + jinja2 template

# ansible_host 为清单上的 IP
bind {{ ansible_host }}

基于此,我们就可以实现基于各服务器自适应的服务配置,如下所示:

配置文件模版 redis.conf.j2

bind {{ redis_listen_host }}
protected-mode yes
port {{ redis_listen_port }}
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize {{ set_daemon | default('yes') }}
supervised no
pidfile /var/run/redis_{{ redis_listen_host }}.pid
loglevel notice
logfile /var/log/redis/redis_{{ redis_listen_host }}.log
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /var/lib/redis
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec

剧本定义

---
- hosts: ecs
  gather_facts: yes
  vars:
    redis_listen_host: "{{ ansible_eth0.ipv4.address }}"
    redis_listen_port: 6380
  tasks:
    - name: "基于 Facts 生成 Redis 配置"
      template:
        src: templates/redis.conf.j2
        dest: /tmp/redis.conf

执行命令

$ ansible-playbook jinja2-demo-0.yml
PLAY [ecs] ******
TASK [Gathering Facts] ******
ok: [ecs-1.aliyun.sz]
ok: [huawei]
TASK [基于 Facts 生成 Redis 配置] ******
changed: [ecs-1.aliyun.sz]
ok: [huawei]
PLAY RECAP ******
ecs-1.aliyun.sz            : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
huawei                     : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

查看文件

$ ansible 'ecs' -m shell -a "head -n5 /tmp/redis.conf"
ecs-1.aliyun.sz | CHANGED | rc=0 >>
bind 172.25.163.48
protected-mode yes
port 6380
tcp-backlog 511
timeout 0
huawei | CHANGED | rc=0 >>
bind 192.168.0.101
protected-mode yes
port 6380
tcp-backlog 511
timeout 0

OK,可以看到,我们基于 facts + jinja2 实现个性化的 redis 配置文件。 jinja2 算是一项比较通用的技术,不仅用在 Ansible,Python 中的 Django、Flask 等框架都有广泛使用,所以系统性的掌握它性价比还是很高的~

二、Jinja2 模版语法

Ansible 使用 jinja2 模版引擎,我们先来了解下 jinja2 的语法知识

早先我们在 playbook 是这么引用变量 {{ variable }} 的,其实这里的 {{ }} 就是 jinja 的核心语法之一,除了它以外还有另外两个 {% %}、``,我们分别来看下

  • {{ }} :用来装载 表达式,如变量、运算表达式、比较表达式等
  • {% %} :用来装载 控制语句,如 if 控制结构,for 循环控制结构
  • `` :用来装载 注释,模板文件被渲染后,注释不会包含在最终生成的文件中

基本上 jinja2 的一切特性都是从这三组符号展开的,我们不着急,一个一个来看…

2.1 表达式

{{ }} 表达式

大致内容

2.1.1 变量

先看第一个例子:

模版定义

Test jinja2 variables
my name is {{ username }}.

执行效果,渲染模版时手动传值,供以模版使用,效果等同于 vars 关键字

$ ansible 'ecs[0]' -m template -e "username=Da" -a "src=templates/expression_variables-demo-1.j2 dest=/tmp/test.j2"
ecs-1.aliyun.sz | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "checksum": "893d60bda9b0810037d8732483ad1de78045823a",
    "dest": "/tmp/test.j2",
    "gid": 0,
    "group": "root",
    "md5sum": "6ba43e7ab4675870ee0334ade7bdd6d3",
    "mode": "0644",
    "owner": "root",
    "size": 36,
    "src": "/root/.ansible/tmp/ansible-tmp-1634111293.09-20738-180061502458356/source",
    "state": "file",
    "uid": 0
}

查看文件

$ cat /tmp/test.j2
Test jinja2 variables
my name is Da.

在看个稍微复杂点的

剧本定义

---
- hosts: ecs
  gather_facts: no
  vars:
    str_var: "Da"
    num_var: 18
    list_var: ["Python", "Go"]
    dict_var:
      name: "{{ str_var }}"
      age: "{{ num_var }}"
      skill: "{{ list_var }}"
  tasks:
    - name: "变量传递 至 jinja2 模版"
      template:
        src: templates/expression_variables-demo-2.j2
        dest: /tmp/test.j2

模版定义

Test jinja2 variables
字符串变量:{{ str_var }}
整型变量:{{ num_var }}
列表变量:{{ list_var }}
字典变量:{{ dict_var }}

执行命令

$ ansible-playbook jinja2-demo-1.yml
PLAY [ecs] ******
TASK [变量传递 至 jinja2 模版] ******
changed: [ecs-1.aliyun.sz]
changed: [huawei]
PLAY RECAP ******
ecs-1.aliyun.sz            : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
huawei                     : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

查看文件

$ cat /tmp/test.j2
Test jinja2 variables
字符串变量:Da
整型变量:18
列表变量:[u'Python', u'Go']
字典变量:{u'skill': [u'Python', u'Go'], u'age': 18, u'name': u'Da'}

2.1.2 比较运算

模版定义

Jinja2 比较表达式

{{ 1 == 1 }} {# 返回 True #}

{{ 2 != 1 }} {# 返回 False #}

{{ 2 > 1 }}  {# 返回 True #}

{{ 2 >= 1 }} {# 返回 True #}

{{ 2 < 1 }}  {# 返回 False #}

{{ 2 <= 1 }} {# 返回 False #}

执行效果

$ ansible 'ecs[0]' -m template -a "src=templates/expression_comparison-demo-1.j2 dest=/tmp/test.j2"
ecs-1.aliyun.sz | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "checksum": "b1c42819c64b16488c03a45e1af71ff4eb1d3293",
    "dest": "/tmp/test.j2",
    "gid": 0,
    "group": "root",
    "md5sum": "6c08fd4745825983cf496abb9ac46cec",
    "mode": "0644",
    "owner": "root",
    "size": 63,
    "src": "/root/.ansible/tmp/ansible-tmp-1634111715.29-21192-555943826307/source",
    "state": "file",
    "uid": 0
}

查看文件

$ cat /tmp/test.j2
Jinja2 比较表达式
True
True
True
True
False
False

2.1.3 逻辑运算

模版定义

Jinja2 逻辑运算

{{ (2 > 1) or (1 < 2) }}    {# 只要有一个括号返回 True 即可 #}

{{ (2 > 1) and (1 > 2) }}   {# 两个括号都得返回 True 才行 #}

{{ not true }}              {# 非 True ==  False #}

{{ not True }}              {# 同上 #}

{{ not false }}             {# 非 False == True #}

{{ not False }}             {# 同上 #}

执行效果

$ ansible 'ecs[0]' -m template -a "src=templates/expression_logical-demo-1.j2 dest=/tmp/test.j2"
ecs-1.aliyun.sz | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "checksum": "34f1f77306db50e1ec5cdb90849d36f2fae0454e",
    "dest": "/tmp/test.j2",
    "gid": 0,
    "group": "root",
    "md5sum": "c8ab48b35ec939c923e0fe138eef60bf",
    "mode": "0644",
    "owner": "root",
    "size": 114,
    "src": "/root/.ansible/tmp/ansible-tmp-1634112063.22-21529-92332521163295/source",
    "state": "file",
    "uid": 0
}

查看文件

$ cat /tmp/test.j2
Jinja2 逻辑运算
True
False
False
False
True
True

2.1.4 三元运算

我们可以通过 if 表达式实现三元运算的效果,语法规则与 Python 十分类似,基本语法

<do something> if <something is true> else <do something else>

In[2]:  '小于' if 1 < 2 else '大于'
Out[2]: '小于'

模版定义

if 表达式 jinja2 使用

1 {{ '小于' if 1 < 2 else '大于' }} 2

执行效果

$ ansible 'ecs[0]' -m template -a "src=templates/expression_if-demo-1.j2 dest=/tmp/test.j2"
ecs-1.aliyun.sz | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "checksum": "d6c19b4dbb1b9faf318dd1a9d079972b09e057f9",
    "dest": "/tmp/test.j2",
    "gid": 0,
    "group": "root",
    "md5sum": "87af82bd45d6c3b51eea373f652d381d",
    "mode": "0644",
    "owner": "root",
    "size": 39,
    "src": "/root/.ansible/tmp/ansible-tmp-1634126704.98-32325-990148113389/source",
    "state": "file",
    "uid": 0
}

查看文件

$ cat /tmp/test.j2
if 表达式 jinja2 使用
1 小于 2

2.1.4 算数运算

模版定义

Jinja2 算数运算

{{ 3 + 2 }}   {# 求和: 5 #}

{{ 3 - 4 }}   {# 减法:-1 #}

{{ 3 * 5 }}   {# 乘法:15 #}

{{ 2 ** 3 }}  {# 乘方:8 #}

{{ 7 / 5 }}   {# 除法:1.4 #}

{{ 7 // 5 }}  {# 整除:1 #}

{{ 17 % 5 }}  {# 取模:2 #}

执行效果

$ ansible 'ecs[0]' -m template -a "src=templates/expression_arithmetic-demo-1.j2 dest=/tmp/test.j2"
ecs-1.aliyun.sz | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "checksum": "622bf544c7c391d3ae07b11fbe7fad439490e7cf",
    "dest": "/tmp/test.j2",
    "gid": 0,
    "group": "root",
    "md5sum": "f43e889b6abffd882c22a5d41e798225",
    "mode": "0644",
    "owner": "root",
    "size": 57,
    "src": "/root/.ansible/tmp/ansible-tmp-1634112450.88-22066-279556856379893/source",
    "state": "file",
    "uid": 0
}

查看文件

$ cat /tmp/test.j2
Jinja2 算数运算
5
-1
15
8
1.4
1
2

2.1.5 成员运算

模版定义

Jinja2 成员表达式

{{ 1 in [1, 2, 3] }}                             {# 1 存在于列表中,  返回 True #}

{{ 1 not in (1, 2, 3) }}                         {# 1 不存在于列表中,返回 False #}

{{ "a" in 'abcd' }}                              {# 1 不存在于列表中,返回 False #}

{{ "name" in {"name": "Da", "age": 18} }}        {# name 字段在于字典中,返回 True #}

{{ "gender" in {"name": "Da", "age": 18} }}      {# gender 字段在于字典中,返回 False #}

{{ "Go" in {"name": "Da", "age": 18, "skill": ["Python", "Go"]}.skill }}      {# Go 元素是否在 skill 列表中,返回 True #}

{{ "DevOps" in {"name": "Da", "age": 18, "skill": ["Python", "Go"]}['skill'] }}      {# DevOps 元素是否在 skill 列表中,返回 False #}

执行效果

$ ansible 'ecs[0]' -m template -a "src=templates/expression_member-demo-1.j2 dest=/tmp/test.j2"
ecs-1.aliyun.sz | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "checksum": "07518c5d5c40905280ddec91368a2e3ac6a82583",
    "dest": "/tmp/test.j2",
    "gid": 0,
    "group": "root",
    "md5sum": "100f5655ba1e892c44f17dd46bc0bc2e",
    "mode": "0644",
    "owner": "root",
    "size": 148,
    "src": "/root/.ansible/tmp/ansible-tmp-1634112908.08-22582-277982919935613/source",
    "state": "file",
    "uid": 0
}

查看文件

$ cat /tmp/test.j2
Jinja2 成员表达式
True
False
True
True
False
True
False 

2.1.6 过滤器

过滤器也可以直接在 {{ }} 中使用,用法在 playbook 中一样,先回顾下此前学过的过滤器内容

模版定义

Jinja2 过滤器
my name is {{ da | capitalize }}.

执行效果

$ ansible 'ecs[0]' -m template -a "src=templates/expression_filter-demo-1.j2 dest=/tmp/test.j2"
ecs-1.aliyun.sz | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "checksum": "9824ca3a09b7b55deb3e8ab78f4a8e8389584803",
    "dest": "/tmp/test.j2",
    "gid": 0,
    "group": "root",
    "md5sum": "c2a7187567ba6a412a3fed4ea2b11fe8",
    "mode": "0644",
    "owner": "root",
    "size": 31,
    "src": "/root/.ansible/tmp/ansible-tmp-1634113897.73-23643-75275671536157/source",
    "state": "file",
    "uid": 0
}

查看文件

$ cat /tmp/test.j2
Jinja2 过滤器
my name is Da.

2.1.7 tests

tests 在 jinja2 自然也是可以的,老规矩先复习下

模版定义

Jinja2 Tests 判断

{{ username is defined }}

{{ password is undefined }}

{{ '/tmp' is exists }}

{{ '/tmp/testfile' is file }}

{{ '/tmp' is directory }}

执行效果

$ ansible 'ecs[0]' -m template -e "username=Da" -a "src=templates/expression_tests-demo-1.j2 dest=/tmp/test.j2"
ecs-1.aliyun.sz | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "checksum": "9ba832404175d5a702941d0267d0770b462ea1a8",
    "dest": "/tmp/test.j2",
    "gid": 0,
    "group": "root",
    "md5sum": "805b7a379b9eb25909aec930662d95ae",
    "mode": "0644",
    "owner": "root",
    "size": 51,
    "src": "/root/.ansible/tmp/ansible-tmp-1634114252.36-24012-167926043248952/source",
    "state": "file",
    "uid": 0
}

查看文件

$ cat /tmp/test.j2
Jinja2 Tests 判断
True
True
True
False
True

2.1.8 lookup

lookup 插件的主要功能是拉取数据,例如从剧本中的数据容器、系统文件、服务等等

模版定义

lookup jinja2 使用

文件内容:{{ lookup('file', '/tmp/t1.txt') }}
系统变量 Path:{{ lookup('env','PATH') }}

执行效果

$ ansible 'ecs[0]' -m template -a "src=templates/expression_lookup-demo-1.j2 dest=/tmp/test.j2"
ecs-1.aliyun.sz | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "checksum": "e099dca996b690545a6a45a56793ab6fbbe20aff",
    "dest": "/tmp/test.j2",
    "gid": 0,
    "group": "root",
    "md5sum": "fe0890921d3bb66126a1858aca8c81a3",
    "mode": "0644",
    "owner": "root",
    "size": 184,
    "src": "/root/.ansible/tmp/ansible-tmp-1634114867.89-24590-240242574038716/source",
    "state": "file",
    "uid": 0
}

查看文件

$ cat /tmp/test.j2
lookup jinja2 使用
文件内容:t1 file.
系统变量 Path:/root/.pyenv/shims:/root/.pyenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/local/prometheus

2.2 控制语句

{% %} 控制语句

上面对 {{}} 有了一个基本的了解,下面我们看 {% %} 控制语句,它的主要用途包括 变量声明条件判断循环 以及模版的 包含导入继承等等

大致内容

2.2.0 变量声明

先来看最基本的变量声明,语法格式:{% set variable='value' %}

模版定义

set 控制语句 jinja2 使用

{% set username='Da' %}
My name is {{ username }}.

执行效果

$ ansible 'ecs[0]' -m template -a "src=templates/control_set-demo-1.j2 dest=/tmp/test.j2"
ecs-1.aliyun.sz | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "checksum": "bd7b989112ef6ca626389dcb80d2926da4780207",
    "dest": "/tmp/test.j2",
    "gid": 0,
    "group": "root",
    "md5sum": "eece8afab519037dcc5a6ed9286d78b7",
    "mode": "0644",
    "owner": "root",
    "size": 47,
    "src": "/root/.ansible/tmp/ansible-tmp-1634132882.13-4326-179634076713335/source",
    "state": "file",
    "uid": 0
}

查看文件

$ cat /tmp/test.j2
set 控制语句 jinja2 使用
My name is Da.

2.2.1 条件判断

条件判断,jinja2 的条件判断是通过 if 条件语句,基本结构为三种

if 结构

{% if 条件 %}
...
{% endif %}

if else 结构

{% if 条件 %}
...
{% else %}
...
{% endif %}

if elif else 结构

{% if 条件一 %}
...
{% elif 条件二 %}
...
{% elif 条件N %}
...
{% endif %}

模版定义

if 控制语句 jinja2 使用

{% set username='Da' %}
{% set password='123123' %}
{% if username=='Da' and password=='123123' %}
   登录成功~
{% elif username=='Da' or password=='123123' %}
   用户名或密码错误!
{% else %}
   登录失败!
{% endif %}

执行效果

$ ansible 'ecs[0]' -m template -a "src=templates/control_if-demo-1.j2 dest=/tmp/test.j2"
ecs-1.aliyun.sz | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "checksum": "03fd800cfeae0e35e3ba4ab5faad2cd0d9b62e26",
    "dest": "/tmp/test.j2",
    "gid": 0,
    "group": "root",
    "md5sum": "47483a89432ded0f8812d5b4f5d1c0aa",
    "mode": "0644",
    "owner": "root",
    "size": 48,
    "src": "/root/.ansible/tmp/ansible-tmp-1634133411.82-5184-5999937262592/source",
    "state": "file",
    "uid": 0
}

查看文件

$ cat /tmp/test.j2
if 控制语句 jinja2 使用
   登录成功~

2.2.2 循环迭代

接下来是循环,这可是重头戏,提起一口气,准备开干吧!

1. 列表遍历

先来个最简单的 for 循环遍历 list 的示例

模版定义

for 控制语句 jinja2 使用

{% for i in [1, 2, 3] %}
元素:{{ i }}
{% endfor %}

执行效果

$ ansible 'ecs[0]' -m template -a "src=templates/control_for-demo-1.j2 dest=/tmp/test.j2"
ecs-1.aliyun.sz | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "checksum": "e5673a43aec2c6890bb2965fe31ae3bcfd62284e",
    "dest": "/tmp/test.j2",
    "gid": 0,
    "group": "root",
    "md5sum": "cc20e94475195b122c6079b7c55cf261",
    "mode": "0644",
    "owner": "root",
    "size": 65,
    "src": "/root/.ansible/tmp/ansible-tmp-1634133741.51-5480-266927481354358/source",
    "state": "file",
    "uid": 0
}

查看文件

$ cat /tmp/test.j2
for 控制语句 jinja2 使用
元素:1
元素:2
元素:3

默认元素后面是会附加 “换行” 的效果,如果不希望它换行,可以这么做

模版定义

for 语句的右边结束符 以及 endfor 左边开始符 加上 -

for 控制语句 jinja2 使用

{% for i in [1, 2, 3] -%}
元素:{{ i }}
{%- endfor %}

查看文件

$ cat /tmp/test.j2
for 控制语句 jinja2 使用
元素:1元素:2元素:3

可以看到,所有元素直接接连拼在了一起,我们可以自定义分割符,如下

模版定义

{% for i in [1, 2, 3] -%}

{# 两种方式效果相同 #}
元素:{{ i }}{{ ',' }}
{# 元素:{{ i~',' }} #}
{%- endfor %}

查看文件

$ cat /tmp/test.j2
for 控制语句 jinja2 使用
元素:1,元素:2,元素:3,

在 jinja2 中 波浪符 ~ 为字符串连接符,常用于将波浪符 ~ 将 迭代变量 或 其他字符串连在一起,你可以理解为 Python 中的 +,如下所示:

{% for i in [1, 2, 3] -%}
{{ i~',' }}
{%- endfor %}

等于

for i in [1, 2, 3]:
    str(i)+','
2. 字典遍历

模版定义

通过 字典的 iteritems() 方法获取 keyvalue

for 控制语句 jinja2 使用

{% for i in {'name': 'Da', 'age': 18}.iteritems() %}
{{ key ~ ':' ~ val }}
{% endfor %}

执行效果

$ ansible 'ecs[0]' -m template -a "src=templates/control_for-demo-2.j2 dest=/tmp/test.j2"
ecs-1.aliyun.sz | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "checksum": "ad1b88881c2e63d165680df48a84b6439971db26",
    "dest": "/tmp/test.j2",
    "gid": 0,
    "group": "root",
    "md5sum": "18992c00f35cce54f4d2df0fee74dc74",
    "mode": "0644",
    "owner": "root",
    "size": 47,
    "src": "/root/.ansible/tmp/ansible-tmp-1634210315.83-5571-259042812590635/source",
    "state": "file",
    "uid": 0
}

查看文件

$ cat /tmp/test.j2
for 控制语句 jinja2 使用
age:18
name:Da

基本用法和 Python 没太大区别

for key, value in {'name': 'Da', 'age': 18}.items():
    print(f'{key}:{value}')
name:Da
age:18
3. 内置变量

我们可以通过内置变量 loop.index 获取当前是第几次循环,示例如下:

模版定义

for 控制语句 jinja2 使用

{% for i in ['Da','Yo','Ho'] %}
{{ '第' ~ loop.index ~ '次遍历,用户名称:' ~ i   }}
{% endfor %}

执行效果

$ ansible 'ecs[0]' -m template -a "src=templates/control_for-demo-3.j2 dest=/tmp/test.j2"
ecs-1.aliyun.sz | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "checksum": "e635899d0b3b11507a6f732e3f1b7615e892e90e",
    "dest": "/tmp/test.j2",
    "gid": 0,
    "group": "root",
    "md5sum": "d6f8c1f9cc38a9a4e1979492f75e1e78",
    "mode": "0644",
    "owner": "root",
    "size": 134,
    "src": "/root/.ansible/tmp/ansible-tmp-1634210652.82-6250-154771205134999/source",
    "state": "file",
    "uid": 0
}

查看文件

$ cat /tmp/test.j2
for 控制语句 jinja2 使用
第1次遍历,用户名称:Da
第2次遍历,用户名称:Yo
第3次遍历,用户名称:Ho

除了 loop.index 外,还有其他内置变量,这里贴下,大致了解下过个眼熟

内置变量 描述
loop.index 当前循环操作为整个循环的第几次循环,以 1 开始
loop.index0 当前循环操作为整个循环的第几次循环,以 0 开始
loop.revindex 当前循环操作距离整个循环结束还有几次,到 1 结束
loop.revindex0 当前循环操作距离整个循环结束还有几次,到 0 结束
loop.first 当操作可迭代对象中的第一个元素时,此变量的值为 true
loop.last 当操作可迭代对象中的最后一个元素时,此变量的值为 true
loop.length 可迭代对象的长度
loop.depth 当使用递归的循环时,当前迭代所在的递归中的层级,层级序号从 1 开始
loop.depth0 当使用递归的循环时,当前迭代所在的递归中的层级,层级序号从 0 开始
loop.cycle() 辅助函数,通过这个函数我们可以在指定的一些值中进行轮询取值(todo)
4. 循环判断

基于已学的内容,我们基本可以写出循环内嵌套判断的 jinja2 代码,例如:打印列表 [1,2,3,4,5] 中大于 3 的元素


文章作者: Da
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Da !
  目录