Flask模板引擎之Jinja2语法介绍
作者:李辉 发布时间:2021-11-15 21:08:11
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(空格控制)
默认的设置:
如果末尾有换行符,则去除;
其他空格原样保留。
也就是说,下面这几行:
<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
来源:https://zhuanlan.zhihu.com/p/23669244
猜你喜欢
- 上一篇说了vue单页面解决解决SEO的问题只是用php预处理了meta标签但是依然没有内容填充,所以对于内容抓取依然有些乏力,只是解决了从无
- let和const声明的变量只在代码块内有效{let a = 10;var b = 1;}a // ReferenceError: a is
- 本文实例讲述了Python面向对象程序设计类的多态用法。分享给大家供大家参考,具体如下:多态1、多态使用一种事物的多种体现形式,举例:动物有
- 第一步、在detect.py中177行左右,cv.imshow(str(p),im0)之前加上:cv2.putText(im0,f"
- 目录1、sysbench介绍#项目下载地址:2、sysbench安装过程#安装相关依赖#安装过程开始#提示说明:#常规命令行选项#sysbe
- 目录Tornado是什么安装试试看使用tornado框架来写一个web application总结Tornado是什么学委之前在看Jupyt
- 目录1. python内置方法(read、readline、readlines)2. 内置模块(csv)3. 使用numpy库(loadtx
- 关于react与vue中的key之前在学习react的时候,常常遇到循环渲染组件时会提示需要在循环组件中加上key属性,比如有一组列表:im
- 我们在编写Python爬虫时,有时会遇到网站拒绝访问等反爬手段,比如这么我们想爬取蚂蚁短租数据,它则会提示“当前访问疑似黑客攻击,已被网站管
- WSGI(Web Server Gateway Interface):Web服务网关接口,是Python中定义的服务器程序和应用程序之间的接
- 一、添加user到group第一种:user.groups.add(1) # add by id第二种:from django.contri
- 1. 概述Promise对象是ES6提出的的异步编程的规范。说到异步编程,就不得不说说同步和异步这两个概念。从字面意思理解同步编程的话,似乎
- 能坚持全部做完的都是高手直入主题建库建表插入数据代码直接按顺序复制就可以-- 建库CREATE DATABASE `emp`;-- 打开库U
- 从这节开始,将会给大家介绍几个ASP中的三大通用类,它贯穿于我所设计的三层架构中,是对ASP语法的扩展,可以提高很多细节处理上的效率,可以算
- 示意图:html:{# 用户管理 #} <div id="userManageDiv" style=&
- 前言:由于使用Django框架来做网站,需要动态显示数据库内的信息,所以读取数据库必须要做,写此博文来记录。接下来分两步来做这个事,添加网页
- 序言是我太久没发了吗?昨天没人看,那么今天来点特别的~不仅把好看的视频全部pa下来,咱们还要实现自动评论、点赞、关注三连~宝,你也可以顺手给
- 在WEB2.0这个词未出现之前,是没有所谓的WEB1.0之说的,那时候的互联网也是没有时代之分的,能上的网站不多,值得上的网站更不多,很多的
- 其实就是利用文件“global.asa”!许多ASP编程新手都想知道这东西是什么?事实上,global.asa就是一个事件驱动程序,其中共包
- 前面是分部讲解,完整代码在最后。导入模块 :import osfrom shutil import copy, rmtreeimport r