挺久之前氵的笔记
0. jinja2 vs Django template
性能上
jinja2能够比Django的模版引擎快10到20倍
语法上
概括来说,可以总结为:Jinja的语法更接近于python的语法,Jinja模版中可以使用某些Python表达式的子集。
例如,拼接列表操作中,可以看出Jinja中过滤器更像是对象的方法的调用:
Django:
1
2{{ items|join:", " }}
## {{obj|filter_name:param}}Jinja:
1
2{{ items|join(', ') }}
## {{obj|filter_name(param)}}
- 更多详细的不同可以参考官方文档中相关内容
1.简介
Jinja模版与普通的html相比,包含两个特殊的部分:
- 标签:用于控制模版的逻辑
- 变量/表达式:用于在模版渲染时替换为值
Jinja中的默认分隔符如下:
{% ... %}
用于语句(标签){{ ... }}
用于打印表达式的输出{# ... #}
用于注释# … ##
行语句,需要应用程序启用此功能,功能类似于{% ... %}
,例如,以下两段示例完全等效:1
2
3
4
5
6
7
8
9
10
11<ul>
# for item in seq
<li>{{ item }}</li>
# endfor
</ul>
<ul>
{% for item in seq %}
<li>{{ item }}</li>
{% endfor %}
</ul>
关于行语句,由于功能完全类似于{% ... %}
,可以忽略
2.基本语法
2.1 变量
除了普通的字符串变量,Jinja2还支持列表、字典和对象,你可以这样获取变量值:
1 | {{ mydict['key'] }} |
2.2 变量赋值
1 | {% set navigation = [('index.html', 'Index'), ('about.html', 'About')] %} |
2.3 控制结构
2.3.1 for
使用方法:
1 | <h1>Members</h1> |
循环语句中字典可能无序,可使用dictsort过滤器
相比于Python中的for循环,使用Jinja时,在for循环的循环体中可以使用一些特殊的变量:
2.3.2 if
if的使用十分类似于Python中的if。
1 | {% if kenny.sick %} |
2.4 宏
Jinja中的宏(macro)类似于常规编程语言中的宏。宏的存在是为了替换简单的多次重复的代码。
例如,可以首先定义一个宏:
1 | {% macro input(name, value='', type='text', size=20) -%} |
然后可以像命名空间中的函数一样调用该宏:
1 | <p>{{ input('username') }}</p> |
*如果宏是在其他模板中定义的,则必须首先将其[导入](#2.7 import)*。
2.5 块——模板继承
块的作用主要体现在模板继承。
在父模版中:
1 | {# base.html #} |
子模版中:
1 | {% extends 'base.html' %} |
在子模板的开头定义了{% extend 'base.html' %}
语句来声明继承,此后在子模板中由{% block block_name %}`和`{% endblock %}
所包括的语句块,将会替换父模板中同样由{% block block_name %}`和`{% endblock %}
所包括的部分。
- 模板不支持多继承,也就是子模板中定义的块,不可能同时被两个父模板替换。
- 模板中不能定义多个同名的块,子模板和父模板都不行,因为这样无法知道要替换哪一个部分的内容。
- 建议在
endblock
关键字后也加上块名,比如{% endblock block_name %}
。可提高程序可读性。 - 若不希望父模板中的块被子模板替换,可在子模版的块中使用
{{ super() }}
。 - 默认情况下,块内语句是无法访问块外作用域中的变量。如果想在块内访问块外的变量,需要在块声明时添加
scoped
关键字:{% block block_name scoped %}{% endblock %}
2.6 include
include
用于实现代码重用的功能。通过{% include %}
语句,可以将另一个模板加载到当前模板中,并直接渲染在当前位置上。
1 | {% include 'header.html' %} |
当”include”的模板文件不存在时,程序会抛出异常。可以加上”ignore missing”关键字,这样如果模板不存在,就会忽略这段{% include %}
语句。
1 | {% include 'footer.html' ignore missing %} |
{% include %}
语句还可以跟一个模板列表:
1 | {% include ['footer.html','bottom.html','end.html'] ignore missing %} |
上例中,程序会按顺序寻找模板文件,第一个被找到的模板即被加载,而其后的模板都会被忽略。如果都没找到,那整个语句都会被忽略。
2.7 import
一个模版中定义的[宏(macro)](#2.4 宏)可以被不同的模板使用,因此可以将其声明在一个单独的模板文件中。需要使用时import
进行导入。
import
的语法类似于python中的import
1 | {% import 'form.html' as form %} |
或
1 | {% from 'form.html' import input %} |
3. 上下文
在Flask应用中的模板可以使用到请求上下文中的环境变量,及一些辅助函数。
例如:
1 | {{ request.url }} |
上下文变量和函数都可以自定义:
1 | from flask import current_app |
函数用@app.context_processor
装饰器修饰,它是一个上下文处理器,它的作用是在模板被渲染前运行其所修饰的函数,并将函数返回的字典导入到模板上下文环境中,与模板上下文合并。
自定义函数方法如下:
1 | import time |
1 | <p>Current Time is: {{ current_time() }}</p> |
4. 过滤器
变量可以通过过滤器被修改。过滤器可以被认为是一种转换函数,使用过滤器利用的是管道符|
。输入的参数就是其所修饰的变量,一些可选参数可以包含在括号中,返回的就是变量转换后的值。过滤器的使用举例如下:
1 | {{ "<p>test</p>"|striptags|upper }} |
1 | {{ listx|join(', ') }} |
Jinja内置的过滤器如下图所示
这些过滤器具体的作用可以参考官方文档
同时,还可以使用自定义的过滤器。自定义过滤器可以通过两种方式实现:
1 | # 方式一,通过app.add_template_filter方法 |
随后可以使用自定义的过滤器
1 | {{ listx|list_reverse }} |