Jinja2模板引擎官方文档详细介绍了其中的API函数、沙箱、模板设计文档等,这里主要就一些常用的知识点进行总结。
常见的几种模板语句如下:
{%...%} #运行Jinja2的语句;
{{…}} #在页面中打印Jinja2运行的结果
{#...#} #注释
看下面的例子:
(1)views.py
from flask import render_template
@app.route('/index')
def index():
return render_template('index1.html',
name='kikay',
age=20)
(2)templates文件夹下新建模板index1.html:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Testtitle>
head>
<body>
<p>测试p>
<p>直接输出姓名:{{name}}p>
{#这是注释:判断是否存在age#}
{%if age%}
<p>年龄:{{age}}p>
{%else%}
<p>不存在年龄p>
{%endif%}
body>
html>
输出效果:
如果想输入原始的Jinja2语句,而不是作为特殊字符进行解析,可以包含在{%raw%}…{%%endraw}
中:
views.py
@app.route('/raw')
def raw():
return render_template('raw.html',name='kikay')
raw.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Rawtitle>
head>
<body>
<div>
<p>姓名:{{name}}p>
{%raw%}
<p>转义姓名:{{name}}p>
{%endraw%}
div>
body>
html>
效果如下:
上面的例子都需要调用render_template('*.html',var_key=***)
来渲染模板。其中的函数render_template是把Jinja2模板引擎集成到程序中。Jinja2 能识别所有类型的变量,甚至是一些复杂的类型,例如列表、字典和对象。
添加一些控制语句,index2.html如下:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{title}}title>
head>
<body>
<div>
{%if author%}
<h1>Hello,{{author}}h1>
{%else%}
<h1>Nobodyh1>
{%endif%}
div>
body>
html>
views.py:
@app.route('/index2')
def index2():
author='kikay'
return render_template('index2.html',
author=author)
输出:
注释掉author:
@app.route('/index2')
def index2():
author='kikay'
return render_template('index2.html')
#author=author)
效果如下:
当参数不存在时,Jinja2模板在渲染时直接忽略掉。更复杂一些,现在还要输出作者好友的列表。
index3.html:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Firendstitle>
head>
<body>
<div>
<h1>作者:{{author.name}}h1>
<table>
<thread>
<th>姓名th>
<th>年龄th>
thread>
{%for f in author.friends%}
<tr>
<td>{{f.name}}td>
<td>{{f.age}}td>
tr>
{%endfor%}
table>
div>
body>
html>
views.py:
@app.route('/index3')
def index3():
author={
'name':'kikay',
'age':20,
'friends':[
{'name':'Andy','age':60},
{'name':'Tom','age':29},
{'name':u'小花','age':18}
]
}
return render_template('index3.html',
author=author)
效果如下:
这里需要指出的是,输出带有中文时,注意编码的问题。类似于Python中函数的定义,Jinja2模板引擎中的macro关键字可以看成是一个函数的定义:
{%macro showinfo(info)%}
这是{{info}}!!!<br />
{%endmacro%}
{%for info in infos%}
{{showinfo(info)}}
{%endfor%}
随着应用的拓展,我们可能在多个页面中使用了相同的HTML代码,并且需要每一个页面都同步,和其他模板引擎一样,Jinja2也支持模板继承。我们在templates下新建一个layout_base.html文件,内容如下:
<html lang="en">
<head>
<meta charset="UTF-8">
{%if title%}
<title>{{title}}title>
{%else%}
<title>No titletitle>
{%endif%}
{%block script%}
<script src="test.js">script>
{%endblock%}
head>
<body>
<div>
{%block t1%}{%endblock%}
<p>----------模板分隔符------------p>
{%block t2%}{%endblock%}
div>
body>
html>
里面有3个block标签,这是为继承该模板的html模板替换使用的。新建index4.html继承layout_base.html:
{%extends 'layout_base.html'%}
{%block script%}
{{super()}}
<script src="test2.js">script>
{%endblock%}
{%block t1%}
{%if author%}
<h1>Hello,{{author.name}}h1>
{%else%}
<h1>Nobodyh1>
{%endif%}
{%endblock%}
{%block t2%}
<table>
<thread>
<th>姓名th>
<th>年龄th>
thread>
{%for f in author.friends%}
<tr>
<td>{{f.name}}td>
<td>{{f.age}}td>
tr>
{%endfor%}
table>
{%endblock%}
效果如下:
extends指明该模板是从哪个模板继承而来的。上面例子中的{{super()}},因为模板中其中包含的内容不是空的,所以需要用{{super()}}来获取原来的内容。如果一个html中包含1个以上的extends标签就会报错,即最多继承于1个模板。
Flask集成了Bootstrap包,可以使用Flask-Bootstrap来渲染模板,首先需要安装(利用pip):
pip install flask-bootstrap
具体过程参见以前的博客(Flask学习总结笔记(1)– 环境配置)。
在__init__.py
中初始化Flask-Bootstrap:
from flask.ext.bootstrap import Bootstrap
修改后的完整__init__.py
如下:
#!flask/bin/env python
#coding:utf-8
__author__ = 'kikay'
from flask import Flask
from flask.ext.bootstrap import Bootstrap
#定义app对象
app=Flask(__name__)
#定义Bootstrap对象
bootstrap=Bootstrap(app)
from app import views
完成Flask-Bootstrap初始化后,就可以在程序中使用一个包含全部Bootstrap文件的基模板。这个模板利用Jinja2的模板继承机制,让程序扩展一个具有基本页面结构的基模板,其中就有用来引入 Bootstrap 的元素。(官方教程),关于Bootstrap的内容可以参看我的博客(Bootstrap学习总结笔记)。
下面是实现一个导航样式的例子:
bootstrap.html
{%extends 'bootstrap/base.html'%}
{%block html_attribs%}lang="zh-cn"{%endblock%}
{%block metas%}
{{super()}}
<meta charset="UTF-8">
{%endblock%}
{%block styles%}
{{super()}}
<link rel="stylesheet" href="{{url_for('.static',filename='css/block.css')}}">
{%endblock%}
{%block scripts%}
{{super()}}
<script src="{{url_for('.static',filename='js/block.js')}}">script>
{%endblock%}
{%block title%}Flask-Bootstrap{%endblock%}
{%block navbar%}
<div class="container">
<nav class="navbar navbar-inverse">
<div class="navbar-header">
<button type="button" class="btn btn-default navbar-toggle" data-toggle="collapse" data-target="#navbar">
<span class="sr-only">Toggle navigationspan>
<span class="icon-bar">span>
<span class="icon-bar">span>
<span class="icon-bar">span>
button>
<a href="#" class="navbar-brand">网站标题a>
div>
<div class="collapse navbar-collapse" id="navbar">
<ul class="nav navbar-nav">
<li class="active"><a href="#">首 页a>li>
<li><a href="#">新闻a>li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
下拉菜单
<span class="caret">span>
a>
<ul class="dropdown-menu">
<li><a href="#">菜单1a>li>
<li><a href="#">菜单2a>li>
<li><a href="#">菜单3a>li>
ul>
li>
ul>
<form class="nav navbar-form navbar-right">
<div class="form-group">
<input type="text" class="form-control" placeholder="用户名">
div>
<div class="form-group">
<input type="password" class="form-control" placeholder="密码">
div>
<div class="form-group">
<button type="submit" class="btn btn-primary form-control">提 交button>
div>
form>
div>
nav>
div>
{%endblock%}
{%block content%}
<div class="container">
<div class="page-header">
{%if author%}
<h1>Hello,{{author.name}}h1>
{%else%}
<h1>Nobodyh1>
{%endif%}
div>
<div class="col-center-block">
{%if author.friends%}
<table class="table table-bordered table-striped table-hover table-condensed">
<thead class="alert-danger">
<th>姓名th>
<th>年龄th>
thead>
{%for f in author.friends%}
<tr class="alert-success">
<td>{{f.name}}td>
<td>{{f.age}}td>
tr>
{%endfor%}
table>
{%endif%}
div>
div>
<script>
script>
{%endblock%}
views.py:
@app.route('/bootstrap')
def bootstrap():
author={
'name':'kikay',
'age':20,
'friends':[
{'name':'Andy','age':60},
{'name':'Tom','age':29},
{'name':u'小花','age':18}
]
}
return render_template('bootstrap.html',
author=author,
title='Bootstrap')
效果如下:
看下源代码,可以更好理解这种渲染的效果。
<htmllang="zh-cn">
<head>
<title>Flask-Bootstraptitle>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="UTF-8">
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="/static/css/block.css">
head>
<body>
<div class="container">
<nav class="navbar navbar-inverse">
<div class="navbar-header">
<button type="button" class="btn btn-default navbar-toggle" data-toggle="collapse" data-target="#navbar">
<span class="sr-only">Toggle navigationspan>
<span class="icon-bar">span>
<span class="icon-bar">span>
<span class="icon-bar">span>
button>
<a href="#" class="navbar-brand">网站标题a>
div>
<div class="collapse navbar-collapse" id="navbar">
<ul class="nav navbar-nav">
<li class="active"><a href="#">首 页a>li>
<li><a href="#">新闻a>li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
下拉菜单
<span class="caret">span>
a>
<ul class="dropdown-menu">
<li><a href="#">菜单1a>li>
<li><a href="#">菜单2a>li>
<li><a href="#">菜单3a>li>
ul>
li>
ul>
<form class="nav navbar-form navbar-right">
<div class="form-group">
<input type="text" class="form-control" placeholder="用户名">
div>
<div class="form-group">
<input type="password" class="form-control" placeholder="密码">
div>
<div class="form-group">
<button type="submit" class="btn btn-primary form-control">提 交button>
div>
form>
div>
nav>
div>
<div class="container">
<div class="page-header">
<h1>Hello,kikayh1>
div>
<div class="col-center-block">
<table class="table table-bordered table-striped table-hover table-condensed">
<thead class="alert-danger">
<th>姓名th>
<th>年龄th>
thead>
<tr class="alert-success">
<td>Andytd>
<td>60td>
tr>
<tr class="alert-success">
<td>Tomtd>
<td>29td>
tr>
<tr class="alert-success">
<td>小花td>
<td>18td>
tr>
table>
div>
div>
<script>
script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js">script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js">script>
<script src="/static/js/block.js">script>
body>
html>
在Flask-Bootstrap中,支持的block样式如下表:
这里不再一一介绍,在实际应用中可以自己体会。另外上面用到了url_for函数做路由的映射,具体使用可以参见我前面的博客(Flask学习总结笔记(2)– Hello world程序)中关于构造Url的内容。这里引入了js和css文件,对应的文件结构如下:
关于Flask-Jinja2模板引擎的使用问题就讲到这里,以后在实际使用过程中,再慢慢总结与领会。