BlackA,Talk is cheap,Show me the code.
我们在上一节中学习了Jinja2模板引擎的基本用法,并用Jinja2模板生成了一些简单的HTML页面。但是Jinja2的强大功能不止于此,这一节中我们将会继续学习Jinja2中的控制语句。
Jinja2提供了类似Python语法的 if 语句,用来控制渲染模板的哪一部分,这有点像C语言中的条件编译,但是远比条件编译的功能强大。我们先来看一个例子,在这个例子中,我们仿照V2EX的登录功能,当用户未登录时,在浏览器的右上角显示 “首页”、“注册”、和 ”登录“ 三个按钮,当用户登录后,显示 “首页”、“用户名”、”设置“、和 “登出” 四个按钮:
这次我们先来看看Python程序代码:
from flask import Flask,render_template
app = Flask(__name__)
# 因为我们还没有学习cookie,所以这里使用is_login来模拟用户是否登录
# 当is_login的值为1时,代表已经登录,为0代表未登录
@app.route("/<int:is_login>/")
def index(is_login):
if is_login == 1:
# 如果用户已经登录,得到用户对应的信息,并传给模板渲染
# 因为我们还没有学习数据库操作,所以这里只使用固定的值来渲染模板
user = {"username" : "blacka","age" : 18}
return render_template("index.html",user = user)
else:
# 如果用户没有登录,则仅仅渲染模板而不传递用户的信息
return render_template("index.html")
if __name__ == "__main__":
app.run(debug = True)在上面这个程序中,我们先确定用户是否登录,如果用户已经登录,我们就从数据库中查询对应的用户信息,并把用户信息传递给模板进行渲染;如果用户没有登录,我们就什么也不传递,直接渲染模板,这就要我们的模板可以判断flask程序是否传递了需要渲染的用户信息,即user这个字段值是否为空,如果为空就说明用户没有登录,显示 “首页”、“注册”、和 ”登录“ 三个按钮,反之说明用户已经登录,显示 “首页”、“用户名”、”设置“、和 “登出” 四个按钮:
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<title>Hello</title>
</head>
<body>
{# if 语句使用一个大括号和一个井号扩起 #}
{% if user %}
{# 如果定义了user这个变量就渲染这里 #}
<a href="#">首页</a>
<a href="#">{{user.username}}</a>
<a href="#">设置</a>
<a href="#">登出</a>
{% else %}
{# 如果没有定义就渲染这里 #}
<a href="#">首页</a>
<a href="#">注册</a>
<a href="#">登录</a>
{# 使用endif来标识if语句块的结束 #}
{% endif %}
</body>
</html>下面是这个程序的运行结果:
提供上面这个例子我们可以看出 if 语句的一般语法格式:
{% if 条件1 %}
语句块1
[ {% elif 条件2 %} ]
[ 语句块2 ]
...
[ {% else %} ]
[ 语句块3 ]
{% endif %}在Jinja2中控制语句(if、for)使用 ”{%“ 和 ”%}“ 括起来,由 ”[“ 和 "]"括起来的部分代表是可选的,因为HTML会忽略源文件中的空白,所以无法使用缩进来确定 if 语句的结尾,需要使用 “{% endif %}” 表示 if 语句的结尾。
if 后面的条件可以写类似Python的条件表达式,具体的细节可以参考官方文档。
Jinja2不仅仅提供了 if 语句用来控制条件,还提供了 for 语句用来循环的渲染某一个语句,当我们需要动态的生成一个列表或者表格的时候,使用 for 循环可以化简我们的工作量:
# 当用户访问/books/时在浏览器上显示书籍信息的列表
from flask import Flask,render_template
app = Flask(__name__)
@app.route("/books/")
def show_books():
# 一个字典列表存放书籍
books = [
{
"姓名" : "红楼梦",
"作者" : "曹雪芹",
"价格" : 109
},
{
"姓名" : "三国演义",
"作者" : "罗贯中",
"价格" : 120
},
{
"姓名" : "水浒传",
"作者" : "施耐庵",
"价格" : 119
},
{
"姓名" : "西游记",
"作者" : "吴承恩",
"价格" : 108
}
]
# 传递字典列表给Jinja2框架
return render_template("books.html",books = books)
if __name__ == "__main__":
app.run(debug = True)<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<title>书籍信息</title>
</head>
<body>
<!-- 无序列表 -->
<ul>
{# 循环遍历列表,语法格式与python类似 #}
{% for book in books %}
<!-- 列表项 -->
<li>
{# 循环遍历字典,除了items()方法外, #}
{# 还可以使用keys()、values()、 #}
{# iteritems()、iterkeys()等字典方法 #}
{% for k,v in book.items() %}
{{k}} : {{v}}
{% endfor %}
</li>
{% endfor%}
</ul>
</body>
</html>这个例子虽然有些臃肿,但是它展示如何使用for 循环遍历列表和字典,下面是代码的运行效果:
另外,Jinja2还内置了一些循环变量,可以在循环中访问它们:
# loop.index 当前循环迭代的次数(从 1 开始) # loop.index0 当前循环迭代的次数(从 0 开始) # loop.revindex 到循环结束需要迭代的次数(从 1 开始) # loop.revindex0 到循环结束需要迭代的次数(从 0 开始) # loop.first 如果是第一次迭代,为 True 。 # loop.last 如果是最后一次迭代,为 True 。 # loop.length 序列中的项目数。 # loop.cycle 在一串序列间期取值的辅助函数。
我们可以通过 loop.first 变量实现书籍名字的黑体:
{% for k,v in book.items() %}
{% if loop.first %}
<b> {{k}} : {{v}} </b>
{% else %}
{{k}} : {{v}}
{% endif %}
{% endfor %}
*** 最后,根据官方文档的建议,应在模板中尽量少的使用if 和 for 等控制语句。 ***