Flask模板引擎之Jinja2语法介绍


Posted in Python onJune 26, 2019

Jinja是组成Flask的模板引擎。可能你还不太了解它是干嘛的,但你对下面这些百分号和大括号肯定不陌生:

{% block body %}
 <ul>
 {% for user in users %}
  <li><a href="{{ user.url }}" rel="external nofollow" >{{ user.username }}</a></li>
 {% endfor %}
 </ul>
{% endblock %}

看过《Flask Web开发》,很多人都能写出来这些,但除了书里讲的,你还应该了解一些其他的语法细节。这篇文章就来介绍一些常用的语法和函数,如果想要系统完整的了解Jinja,可以去读它的文档:Jinja2 Documentation。

FAQ

在Jinja网站上的FAQ里,我挑了三个大家可能会比较感兴趣的问题(简单翻译了一下)。

1、为什么要叫Jinja?

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

2、Jinja的速度怎么样?

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

3、把逻辑判断(Logic)放到模板里是个好主意吗?

毫无疑问,你放到模板里逻辑判断(Logic)应该越少越好。但为了让大家都开心,适当的逻辑判断是需要的。尽管如此,它有很多对于你能做什么,不能做什么的限制。

出于诸多考虑(速度,易读性等等),Jinja既不允许你放置任意的Python代码,也不允许所有的Python表达式。这也是为什么我们要了解Jinja2的语法。

Delimiters(分隔符)

{% ... %} 语句(Statements)
{{ ... }} 打印模板输出的表达式(Expressions)
{# ... #} 注释
# ... ## 行语句(Line Statements)

多说一下注释,这是单行注释:

{#% for user in users %#}

下面是多行注释:

{# note: commented-out template because we no longer use this
  {% for user in users %}
    ...
  {% endfor %}
#}

Variables(变量)

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

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

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

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

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

Filter(过滤器)

过滤器用来修改变量,使用一个竖线和变量相隔。

{{ items|join(', ') }}

常用的内置过滤器:

  • safe 渲染时不转义
  • capitalize 首字母大写
  • lower 小写
  • upper 大写
  • title 每个单词的首字母都转换成大写
  • trim 去掉首尾空格
  • striptags 去掉值里的HTML标签
  • default 设置一个默认值,如果变量未定义,就用这个默认值替换。类似这样:
{{ my_variable|default('my_variable is not defined') }}
  • random(seq) 返回一个序列里的随机元素
  • truncate(s, length=255, killwords=False, end='...') 截取出指定长度的文章(文章摘要)
  • format(value, *args, **kwargs) 参考Python的字符串格式化函数
  • length 左边如果是列表,输出列表的数量;如果是字符串,则输出字符串的长度
  • ……

完整的fliter列表:http://jinja.pocoo.org/docs/dev/templates/#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):

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

完整的test列表及用法见:Template Designer Documentation

Loop(循环)

在一个for循环内,有一些特殊的变量可以使用,这是几个常用的:

  • loop.index 当前迭代数,可以用来写评论的楼层数(从1开始)
  • loop.index0 同上,不过从0开始迭代
  • loop.revindex 反向的迭代数(基数为1)
  • loop.revindex0 反向的迭代数(基数为0)
  • loop.length 序列的数量
  • loop.first 是否是第一个元素
  • loop.last 是否是最后一个元素
  • ......

完整的列表见:http://jinja.pocoo.org/docs/dev/templates/#for

Whitespace Control(空格控制)

默认的设置:

  1. 如果末尾有换行符,则去除;
  2. 其他空格原样保留。

也就是说,下面这几行:

<div>
  {% if True %}
    yay
  {% endif %}
</div>

渲染后的结果是这样:

<div>

    yay

</div>

Jinja2语句占据的空行,你自己输出的空格,Tab都将保留。

如果要去掉Jinja2语句占据的空行,可以通过设置Jinja2的环境变量实现:

app.jinja_env.trim_blocks = True
app.jinja_env.lstrip_blocks = True

或者像这样手动添加一个减号(注意和%之间没有空格):

<div>
  {% if True -%}
    yay
  {%- endif %}
</div>

两者实现的效果相同,如下:

<div>
    yay
</div>

如果语句块的前后都加上减号:

<div>
  {%- if True -%}
    yay
  {%- endif -%}
</div>

渲染后会是这样:

<div>yay</div>

通过Jinja2提供的环境变量,你可以设置很多东西,比如分隔符(在和其他的语言产生冲突时,可以通过修改分隔符来解决)。具体见:http://jinja.pocoo.org/docs/dev/api/#jinja2.Environment

Escaping(转义)

有时你会想原样输出一些Jinja2语句和分隔符,对于小的内容,可以使用变量表达式来输出,比如输出一个分隔符:

{{ '{{' }}

大的内容块可以使用一个raw块包裹:

{% raw %}
  <ul>
  {% for item in seq %}
    <li>{{ item }}</li>
  {% endfor %}
  </ul>
{% endraw %}

模板继承

你可以创建一个base.html作为基模板,把导航栏、页脚、flash消息、js或css文件等等需要在每一个页面中显示的内容放在基模板里,并添加一个空的块用来放置其他子模板的内容:

{% block content %}{% endblock %}

然后在其他的模板(子模板)里使用这个extends语句继承它,并放置相应的内容到基模板里定义过的空块:

{% extends "base.html" %}
{% block content %}
子模板的内容
{% endblock %}

如果想添加内容到在父模板内已经定义的块,可以使用super函数:

{% block sidebar %}
  <h3>Table Of Contents</h3>
  ...
  {{ super() }}
{% endblock %}

这样可以避免覆盖父块的内容。

全局函数

常用的全局函数有:

  • range([start, ]stop[, step])
  • lipsum(n=5, html=True, min=20, max=100) 为模板生成一些 lorem ipsum。

详细列表见:Template Designer Documentation

其他内容

内容还有很多,比如行语句、控制流、表达式、宏等。不再一一介绍了(写这种介绍文章太累了……)。

具体见文档的模板部分:

Template Designer Documentation 

相关链接

Jinja主页:Jinja2 Documentation

Jinja2文档:Jinja2 Documentation

Jinja2文档模板部分:Template Designer Documentation

Github项目页:pallets/jinja

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现文件名批量替换和内容替换
Mar 20 Python
使用Python编写一个简单的tic-tac-toe游戏的教程
Apr 16 Python
Python3搜索及替换文件中文本的方法
May 22 Python
分享一下如何编写高效且优雅的 Python 代码
Sep 07 Python
Python创建普通菜单示例【基于win32ui模块】
May 09 Python
python利用Tesseract识别验证码的方法示例
Jan 21 Python
使用python获取(宜宾市地震信息)地震信息
Jun 20 Python
python 发送json数据操作实例分析
Oct 15 Python
python数据库开发之MongoDB安装及Python3操作MongoDB数据库详细方法与实例
Mar 18 Python
python 写一个水果忍者游戏
Jan 13 Python
解决hive中导入text文件遇到的坑
Apr 07 Python
Elasticsearch 数据类型及管理
Apr 19 Python
如何使用Python实现自动化水军评论
Jun 26 #Python
详解用pyecharts Geo实现动态数据热力图城市找不到问题解决
Jun 26 #Python
Python 数据可视化pyecharts的使用详解
Jun 26 #Python
python 实现交换两个列表元素的位置示例
Jun 26 #Python
python之信息加密题目详解
Jun 26 #Python
实例详解Python模块decimal
Jun 26 #Python
Python3之不使用第三方变量,实现交换两个变量的值
Jun 26 #Python
You might like
再次研究下cache_lite
2007/02/14 PHP
php清空(删除)指定目录下的文件,不删除目录文件夹的实现代码
2014/09/04 PHP
JavaScript delete 属性的使用
2009/10/08 Javascript
半角全角相互转换的js函数
2009/10/16 Javascript
javascript获得CheckBoxList选中的数量
2009/10/27 Javascript
分享一道笔试题[有n个直线最多可以把一个平面分成多少个部分]
2012/10/12 Javascript
jQuery动态添加删除select项(实现代码)
2013/09/03 Javascript
Javascript实现返回上一页面并刷新的小例子
2013/12/11 Javascript
JavaScript运行机制之事件循环(Event Loop)详解
2014/10/10 Javascript
jQuery的remove()方法使用详解
2015/08/11 Javascript
Angular.js如何从PHP读取后台数据
2016/03/24 Javascript
JavaScript 数组的进化与性能分析
2017/09/18 Javascript
微信小程序实现滚动消息通知
2018/02/02 Javascript
NodeJS安装图文教程
2018/04/19 NodeJs
Vue框架里使用Swiper的方法示例
2018/09/20 Javascript
在vue中使用setInterval的方法示例
2019/04/16 Javascript
配置一个vue3.0项目的完整步骤
2019/04/26 Javascript
用vscode开发vue应用的方法步骤
2019/05/06 Javascript
JavaScript深入V8引擎以及编写优化代码的5个技巧
2019/06/24 Javascript
基于JavaScript获取url参数2种方法
2020/04/17 Javascript
[01:38]女王驾到——至宝魔廷新尊技能&特效展示
2020/06/16 DOTA
Python中有趣在__call__函数
2015/06/21 Python
通过mod_python配置运行在Apache上的Django框架
2015/07/22 Python
Python中在脚本中引用其他文件函数的实现方法
2016/06/23 Python
pygame游戏之旅 载入小车图片、更新窗口
2018/11/20 Python
python面试题Python2.x和Python3.x的区别
2019/05/28 Python
Python 用三行代码提取PDF表格数据
2019/10/13 Python
Python3.7在anaconda里面使用IDLE编译器的步骤详解
2020/04/29 Python
为什么称python为胶水语言
2020/06/16 Python
C#怎么让一个窗口居中显示?
2015/10/20 面试题
奖学金感谢信
2015/01/21 职场文书
匿名检举信范文
2015/03/02 职场文书
2015年出纳个人工作总结
2015/04/02 职场文书
中学教师读书笔记
2015/07/01 职场文书
建国70周年的心得体会(2篇)
2019/09/20 职场文书
关于CentOS 8 搭建MongoDB4.4分片集群的问题
2021/10/24 MongoDB