美文网首页
模板引擎Jinja2语法介绍

模板引擎Jinja2语法介绍

作者: 王奥OX | 来源:发表于2020-02-21 18:18 被阅读0次

    前言

    Flask和Django,以及其它很多Python框架如Ansible,都默认使用Jinja2来作为模版引擎。我们用Jinja2在服务器上直接生成配置和其他文件。 Jinja是一个基于Python设计语言的“全功能模板引擎”,个人认为Jinja语法本身并不复杂,但掌握好基本的Jinja语法会帮助你在构建Ansible、Jenkins、Web等批处理作业时做到事半功倍的效果。

    模板引擎Jinja2语法介绍

    更新历史

    2020年02月20日 - 初稿

    阅读原文 - https://wsgzao.github.io/post/jinja/


    Jinja简介

    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:

    {% 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:

    • sandboxed execution
    • powerful automatic HTML escaping system for XSS prevention
    • template inheritance
    • compiles down to the optimal python code just in time
    • optional ahead-of-time template compilation
    • easy to debug. Line numbers of exceptions directly point to the correct line in the template.
    • configurable syntax

    Jinja2 是一个现代的,设计者友好的,仿照 Django 模板的 Python 模板语言。 它速度快,被广泛使用,并且提供了可选的沙箱模板执行环境保证安全:

    特性:

    • 沙箱中执行
    • 强大的 HTML 自动转义系统保护系统免受 XSS
    • 模板继承
    • 及时编译最优的 python 代码
    • 可选提前编译模板的时间
    • 易于调试。异常的行数直接指向模板中的对应行。
    • 可配置的语法

    为什么要叫Jinja?

    之所以叫Jinja,是因为日本的神社(Jinja)英文单词是temple,而模板的英文是template,两者发音很相似(这么说来,它本来也有可能叫Miao的……)。

    Jinja的速度怎么样?

    和Mako差不多,但比Genshi以及Django的模板引擎快10~20倍。

    把逻辑判断(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语言基础

    注意:Jinja2模版语言,是不区分缩进的,和纯python不同。实际上所有模版语言都不区分缩紧。

    常用标记:

    注释:`{# 这是注释 #}`
    变量:`{{ post.title }}`,或字典元素`{{your_dict['key']}}`,或列表`{{your_list[0]}}`
    多行代码块:`{% 开始 %} HTML标签 {% 结束 %}`
    

    示例:

    {% if user %}
        {{ user }}
    {% else %}
        hello!
        {% for index in indexs %}
            {{ index }} 
    {% endfor %}
    
    

    Delimiters(分隔符)

    {% … %} 语句([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))
    

    Variables(变量)

    除了普通的字符串变量,Jinja2还支持列表、字典和对象,你可以这样获取变量值:

    {{ mydict['key'] }}
    {{ mylist[3] }}
    {{ mylist[myintvar] }}
    {{ myobj.somemethod() }}
    

    获取一个变量的属性有两种方式:

    {{ foo.bar }}
    {{ foo['bar'] }}
    

    这两种方法基本相同(深层次的区别可以暂不考虑)

    Filter 过滤器()

    一个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>
    

    List of Builtin Filters

    Tests(测试,判断)

    Jinja2提供的tests可以用来在语句里对变量或表达式进行测试,如果要测试一个变量,可以在变量后加上“is”和test名,比如:

    {% if user.age is equalto 42 %} {# 这里也可以写成... is equalto(42) #}
    Ha, you are 42!
    {% endif %}
    

    如果要传入参数,可以在test后增加括号,也可以直接写在后面。

    常用的test(未说明的均返回True或False):

    • boolean
    • defined
    • equalto
    • escaped
    • none
    • sequence
    • string
    • number
    • reverse
    • replace

    List of Builtin Tests

    For/If (列表控制结构)

    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.

    List of Control Structures

    For

    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>
    

    循环索引

    • loop.index: 循环当前迭代(从1开始)。
    • loop.index0: 循环当前迭代(从0开始)。
    • loop.revindex: 循环迭代的数量(从1开始)。
    • loop.revindex0: 循环迭代的数量(从0开始)。
    • loop.first: 是否为迭代的第一步。
    • loop.last: 是否为迭代的最后一步。
    • loop.length: 序列中元素的数量。

    If

    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 %}
    

    Ansible Jinja2 模版使用

    更多用法可以阅读参考文章中的链接

    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变量。

    参考文章

    Jinja Documentation

    Jinja2 中文文档

    Flask模板引擎:Jinja2语法介绍

    一篇文章搞懂Jinja2 Template Engine 模版引擎

    Ansible Templating (Jinja2)

    ansible笔记(38):jinja2模板(一)

    Ansible Jinja2 模板使用

    相关文章

      网友评论

          本文标题:模板引擎Jinja2语法介绍

          本文链接:https://www.haomeiwen.com/subject/jlhhqhtx.html