Flask和Django,以及其它不少Python框架如Ansible,都默认使用Jinja2来做为模版引擎。咱们用Jinja2在服务器上直接生成配置和其余文件。 Jinja是一个基于Python设计语言的“全功能模板引擎”,我的认为Jinja语法自己并不复杂,但掌握好基本的Jinja语法会帮助你在构建Ansible、Jenkins、Web等批处理做业时作到事半功倍的效果。html
模板引擎Jinja2语法介绍
2020年02月20日 - 初稿python
阅读原文 - https://wsgzao.github.io/post...nginx
Jinja is a modern and designer-friendly templating language for Python, modelled after Django’s templates. It is fast, widely used and secure with the optional sandboxed template execution environment:git
{% extends "base.html" %} {% block title %}Members{% endblock %} {% block content %} <ul> {% for user in users %} <li><a href="{{ user.url }}">{{ user.username }}</a></li> {% endfor %} </ul> {% endblock %}
Features:github
Jinja2 是一个现代的,设计者友好的,仿照 Django 模板的 Python 模板语言。 它速度快,被普遍使用,而且提供了可选的沙箱模板执行环境保证安全:express
特性:flask
为何要叫Jinja?
之因此叫Jinja,是由于日本的神社(Jinja)英文单词是temple,而模板的英文是template,二者发音很类似(这么说来,它原本也有可能叫Miao的……)。segmentfault
Jinja的速度怎么样?
和Mako差很少,但比Genshi以及Django的模板引擎快10~20倍。api
把逻辑判断(Logic)放到模板里是个好主意吗?
毫无疑问,你放到模板里逻辑判断(Logic)应该越少越好。但为了让你们都开心,适当的逻辑判断是须要的。尽管如此,它有不少对于你能作什么,不能作什么的限制。安全
出于诸多考虑(速度,易读性等等),Jinja既不容许你放置任意的Python代码,也不容许全部的Python表达式。这也是为何咱们要了解Jinja2的语法。
在Jinja官方文档中建议你们能够优先阅读如下2个章节:
在Python中,什么是模版?就是在一个静态HTML加入一些相似变量的标签,而后引擎在渲染这个HTML时候会动态的把变量填入内容,生成一个最终的HTML。
什么是模版引擎?其实就是一种能解析相似Python语言
的标记语言的解释器。
好比咱们在HTML模版中输入一个`<p> {{ post.title }} </p>`,显然这不是真正的HTML语法。可是当Jinja2解释器读取到`{{ ...}}`后知道里面是一个变量,那么就把这个变量替换为真正的值,最后翻译出来就变成了`<p> 大标题 </p>`这样的HTML内容。
Jinja2是一个模版语言,只是相似Python,比较符合Python语法,但不彻底相同!
全部的模版引擎,实际上都差很少,不论是基于VBS语言的ASP模版,仍是基于PHP语言的PHP模版,都不是与本来语言一摸同样,而只是作到尽可能同样而已。
注意:Jinja2
模版语言,是不区分缩进的,和纯python不一样。实际上全部模版语言都不区分缩紧。
经常使用标记:
注释:`{# 这是注释 #}` 变量:`{{ post.title }}`,或字典元素`{{your_dict['key']}}`,或列表`{{your_list[0]}}` 多行代码块:`{% 开始 %} HTML标签 {% 结束 %}`
示例:
{% if user %} {{ user }} {% else %} hello! {% for index in indexs %} {{ index }} {% endfor %}
{% … %} 语句([Statements](http://jinja.pocoo.org/docs/dev/templates/#list-of-control-structures)) {{ … }} 打印模板输出的表达式([Expressions](http://jinja.pocoo.org/docs/dev/templates/#expressions)) {# … #} 注释 # … ## 行语句([Line Statements](http://jinja.pocoo.org/docs/dev/templates/#line-statements))
除了普通的字符串变量,Jinja2还支持列表、字典和对象,你能够这样获取变量值:
{{ mydict['key'] }} {{ mylist[3] }} {{ mylist[myintvar] }} {{ myobj.somemethod() }}
获取一个变量的属性有两种方式:
{{ foo.bar }} {{ foo['bar'] }}
这两种方法基本相同(深层次的区别能够暂不考虑)
一个filter过滤器的本质就是一个function函数。使用格式为:变量名 | 函数
。
它作到的就是,把变量传给函数,而后再把函数返回值做为这个代码块的值。
如:
<!-- 带参数的 --> {{变量 | 函数名(*args)}} <!-- 不带参数能够省略括号 --> {{变量 | 函数名}}
链式调用(管道式):
和命令行的pipline管道同样,能够一次调用多个函数(过滤器),如:
{{ "hello world" | reverse | upper }}
文本块调用(将中间的全部文字都做为变量内容传入到过滤器中):
{% filter upper %} 一大堆文字 {% endfilter %}
Jinja2经常使用过滤器
字符串操做:
safe:禁用转义 <p>{{ '<em>hello</em>' | safe }}</p> capitalize:把变量值的首字母转成大写,其他字母转小写 <p>{{ 'hello' | capitalize }}</p> lower:把值转成小写 <p>{{ 'HELLO' | lower }}</p> upper:把值转成大写 <p>{{ 'hello' | upper }}</p> title:把值中的每一个单词的首字母都转成大写 <p>{{ 'hello' | title }}</p> reverse:字符串反转 <p>{{ 'olleh' | reverse }}</p> format:格式化输出 <p>{{ '%s is %d' | format('name',17) }}</p> striptags:渲染以前把值中全部的HTML标签都删掉 <p>{{ '<em>hello</em>' | striptags }}</p> truncate: 字符串截断 <p>{{ 'hello every one' | truncate(9)}}</p>
列表操做:
first:取第一个元素 <p>{{ [1,2,3,4,5,6] | first }}</p> last:取最后一个元素 <p>{{ [1,2,3,4,5,6] | last }}</p> length:获取列表长度 <p>{{ [1,2,3,4,5,6] | length }}</p> sum:列表求和 <p>{{ [1,2,3,4,5,6] | sum }}</p> sort:列表排序 <p>{{ [6,2,3,1,5,4] | sort }}</p>
Jinja2提供的tests能够用来在语句里对变量或表达式进行测试,若是要测试一个变量,能够在变量后加上“is”和test名,好比:
{% if user.age is equalto 42 %} {# 这里也能够写成... is equalto(42) #} Ha, you are 42! {% endif %}
若是要传入参数,能够在test后增长括号,也能够直接写在后面。
经常使用的test(未说明的均返回True或False):
A control structure refers to all those things that control the flow of a program - conditionals (i.e. if/elif/else), for-loops, as well as things like macros and blocks. With the default syntax, control structures appear inside blocks.
Loop over each item in a sequence. For example, to display a list of users provided in a variable called users:
<h1>Members</h1> <ul> {% for user in users %} <li>{{ user.username|e }}</li> {% endfor %} </ul>
As variables in templates retain their object properties, it is possible to iterate over containers like dict:
<dl> {% for key, value in my_dict.items() %} <dt>{{ key|e }}</dt> <dd>{{ value|e }}</dd> {% endfor %} </dl>
循环索引
The if statement in Jinja is comparable with the Python if statement. In the simplest form, you can use it to test if a variable is defined, not empty and not false:
{% if users %} <ul> {% for user in users %} <li>{{ user.username|e }}</li> {% endfor %} </ul> {% endif %}
For multiple branches, elif and else can be used like in Python. You can use more complex Expressions there, too:
{% if kenny.sick %} Kenny is sick. {% elif kenny.dead %} You killed Kenny! You bastard!!! {% else %} Kenny looks okay --- so far {% endif %}
更多用法能够阅读参考文章中的连接
variables: 能够输出数据
{{ my_variable }} {{ some_dudes_name | capitalize }}
statements: 能够用来建立条件和循环等等
{% if my_conditional %} xxx {% endif %} {% for item in all_items %} {{ item }} {% endfor %}
从上文中第二个variable的例子中能够看出,Jinja2支持使用带过滤器的Unix型管道操做符。有不少的内置过滤器可供使用。
咱们能够仅仅用一堆简单if和for就能够创建创建几乎任何的常规配置文件。不过若是你有意更进一步,Jinja2 Documentation包含了不少有趣的东西可供了解。咱们能够看到Ansibe容许在模板中使用一些额外的模版变量。
按照Ansible template_module, 咱们模板的示例:
- name: Create Nginx SSL configuration template: src: "nginx_ssl.j2" dest: "/etc/nginx/sites-available/{{ project_name }}"
咱们一样能够发如今Ansible Facts中有不少可用的Ansible变量。