静态网页我们可以直接将网页编写为HTML文件,进行保存,当浏览器请求该网页时,服务器会直接将该网页发送给浏览器,这样就实现的网页的访问.
但是如果网页是动态的要怎么办?这就需要一个模板,事先将不会改变的元素放入其中,然后保存为文件,当请求动态内容的时候,由服务器将动态内容填入模板中,发送给浏览器,这样网页就可以随着不同的内容进行动态的变更.
那么怎样将动态的内容写入模板中?
这就是jinja需要干的事情
首先安装flask模块
在编写程序的所在目录新建一个templates文件夹,将模板保存在该文件夹下
定义一个最简单的demo例子,如下代码
from flask import Flask,render_template
app = Flask(__name__)
@app.route('/')
def test():
return render_template('你的模板文件.html',需要传入的变量和值)
if __name__ == '__main__':
app.run(debug=1)
此类主要用来储存全局的渲染并进行配置和从其他地方加载模板对象
构造该类的对象,使用Environment(loader,autoescape,CACHE_SIZE,auto_reload,trim_blocks,lstrip_blocks….)
这里只是列举了几个常用的构造方法
trim_blocks
删除语句后的空白行,默认False
lstrip_blocks
删除语句前的空白行,默认False
loader
加载器
autoescape
是否加载xml/html自动加载功能,默认为True
CACHE_SIZE
缓存大小,加载模板的个数
auto_reload
检测模板位置是否更改,如果是,就重新加载模板
常用方法
add_extension(extension)
添加扩展
from_string(source,globals = None,template_class = None )
从字符串加载模板,返回一个Template对象
get_template(name,parent = None,globals = None )
从加载器中返回一个Template对象
list_templates(extensions = None,filter_func = None )
返回此环境的所有模板列表
select_template(names,parent = None,globals = None )
类似于get_template
导入模板到全局环境中
from jinja2 import *
loader = FileSystemLoader(r'C:\Users\wudi.HAPMMAGNA\PycharmProjects\untitled\templates')
env = Environment(loader=loader, trim_blocks=True, lstrip_blocks=True)
print(env.list_templates())
常用属性
name
返回该模板的名称
filename
返回系统上该模板的文件名
from jinja2 import *
loader = FileSystemLoader(r'C:\Users\wudi.HAPMMAGNA\PycharmProjects\untitled\templates')
env = Environment(loader=loader)
temp = env.get_template('base.html')
print(temp.name)
print(temp.filename)
常用方法
render([context])
向模板中传入变量值,有两种方法,一种是像关键字参数一样传参,另一种是传入字典
generate([ context] )
对于非常大的模板,不能一次性渲染,而要采用分段渲染时,采用此函数
stream([ context] )
和generate一样,但返回一个TemplateStream对象
此时我们需要定义一个模板文件,如下:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>titletitle>
head>
<body>
<h1>这是一个jinja2模板文件h1>
<h2>{{ data }}h2>
body>
html>
现在我们将可以向模板中添加需要的动态改变的内容了,为了更好的了解方法,我们将之落地为a.html文件
from jinja2 import *
loader = FileSystemLoader(r'C:\Users\wudi.HAPMMAGNA\PycharmProjects\untitled\templates')
env = Environment(loader=loader)
temp = env.get_template('base.html')
temp.stream(data='hello jinja2!').dump('a.html')
disable_buffering()
禁用输出缓冲
dump(fp,encoding = None,errors ='strict' )
将整个流写入文件中
enable_buffering(size = 5 )
启用输出缓冲
相应的例子都在上面的代码中
在jinja2中定义了FileSystemLoader和PackageLoader等多个加载器
FileSystemLoader(searchpath,encoding ='utf-8',followlinks = False )
类 从文件中加载模板
PackageLoader(package_name,package_path ='templates',encoding ='utf-8' )
类 从Python包中加载模板
注意 :
jinja2语句在渲染之后会变成空白行,可以采取两种方式消除空行:
一种是可在%后使用
-
来消除空行另一种是在Environment中定义
trim_blocks
和lstrip_blocks
消除空白行
例子:
<div>
{% if True %}
yay
{% endif %}
div>
上面的语句渲染出来会是这样:
<div>
yay
div>
我们如果想要去掉空白行可以这样:
{%- if True %}
yay
{%- endif %}
</div>
{{ 变量 }}
定义一个变量,渲染时会将真实的值传入,将这个变量替换掉,外部花括号是一个print语句
这些变量可以是以下几类:
单个变量
列表 list
和python中用法相同,可以使用下角标进行输出
字典 dict
和python中用法相同,可以使用下角标传key值进行输出
可变参数 *args
和python中用法相同,相当于列表
可变关键字参数 **kwargs
和python中用法相同,相当于字典
类 class
和python中用法相同,使用.
访问属性
传入类
# 模板
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<p>电影名: {{ movie.name }}p>
<p>价格: {{ movie.price }}p>
body>
html>
# flask
from flask import Flask,render_template
app = Flask(__name__)
class Movie(object):
def __init__(self,name,price):
self.name = name
self.price = price
m = Movie('泰坦尼克号3D',100)
@app.route('/')
def test():
return render_template('base.html', movie=m)
if __name__ == '__main__':
app.run(debug=1)
if语句,采用以下方式进行定义
{ %if….% }
语句1
{% elif... %}
语句2
{% else %}
语句3
{ %endif% }
我们看一个例子,使用if语句输出,这里使用flask,便于直观的查看文件
# 模板文件
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
{% if data>0 %}
<h1>{{ data }} > 0h1>
{% elif data==0 %}
<h1>{{ data }} = 0h1>
{% else %}
<h1>{{ data }} < 0h1>
{% endif %}
body>
html>
# flask应用程序
from flask import Flask,render_template
app = Flask(__name__)
@app.route('/')
def test():
return render_template('base.html', data=-2)
if __name__ == '__main__':
app.run(debug=1)
for语句,采用以下形式定义:
- 使用for遍历列表
{% for item in list %}
语句
{% endfor %}
- 使用for遍历字典
{% for k,v in dict.items() %}
语句
{% endfor %}
例子,循环输出li标签
# 模板文件
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<ul>
{% for i in list %}
<li> {{ i }}li>
{% endfor %}
ul>
body>
html>
# flask应用程序
from flask import Flask,render_template
app = Flask(__name__)
@app.route('/')
def test():
list = [1,2,3,4,5,6]
return render_template('base.html',list=list)
if __name__ == '__main__':
app.run(debug=1)
另一个例子,制作一个表格
# 模板文件
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<table border="1">
{% for k,v in dict.items() %}
<tr>
<td>{{ k }}td>
<td>{{ v }}td>
tr>
{% endfor %}
table>
body>
html>
# flask应用程序
from flask import Flask,render_template
app = Flask(__name__)
@app.route('/')
def test():
dict = {1:'a',2:'b',3:'c'}
return render_template('base.html',dict=dict)
if __name__ == '__main__':
app.run(debug=1)
在for循环语句中,可以使用以下特殊变量
loop.index
循环的当前迭代。(1索引)
loop.index0
循环的当前迭代。(0索引)
loop.revindex
循环结束时的迭代次数(1个索引)
loop.revindex0
循环结束时的迭代次数(0索引)
loop.first
如果第一次迭代,则为True
loop.last
如果最后一次迭代则为真。
loop.length
序列中的项目数。
loop.depth
指示当前呈现的递归循环的深度。从1级开始
loop.depth0
指示当前呈现的递归循环的深度。从0级开始
loop.previtem
循环的上一次迭代中的项目。在第一次迭代期间未定义
loop.nextitem
循环的以下迭代中的项。在上一次迭代期间未定义
for循环的控制
使用过滤器在for语句中进行控制,见下面的过滤器
for循环和if判断嵌套
- 第一种方式,直接在嵌套在for语句中
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
{% for i in list %}
{% if i is even %}
<p>{{ i }}p>
{% endif %}
{% endfor %}
body>
html>
- 第二种方式,直接在for语句中写入if
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
{% for i in list if i is even %}
<p>{{ i }}p>
{% endfor %}
body>
html>
set语句
该语句是用来对变量进行赋值,这个变量可以是一个值,也可以是一个语句块
- 对值进行定义,采用以下形式进行定义:
{% set 变量 = 值 %}
对值进行定义的例子
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
{% set boolean = true %}
{% if boolean %}
<p>Truep>
{% endif %}
body>
html>
- 对语句块进行定义,采用以下形式:
{% set 变量 %}
语句
{% endset %}
对语句块进行定义的例子
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
{% set data %}
<p>hello,jinja2!p>
{% endset %}
{{ data }}
body>
html>
with语句
在语句块中新建内部范围,变量只能在内部进行访问,在外部不可见,采用以下形式进行定义:
{% with %}
语句
{% endwith %}
当需要在语句块中新建变量时,可以使用
{% with 变量=值 %}
语句
{% endwith %}
这将等效于
{% with %}
{% set 变量=值 %}
语句
{% endwith %}
表达式符号
算数
+
: 对于数字来说是加号;对字符串来说是连接符号
-
: 减号
/
: 除号
//
: 整除
%
: 取余
*
: 对于数字来说是乘号;对字符串来说重复多次
**
: 幂运算
比较
==
: 相等
!=
: 不等
>=
: 大于等于
<=
: 小于等于
>
: 大于
<
: 小于
逻辑
and
: 并且
or
: 或者
not
: 不是
in
: 在里面
is
: 是
其他
|
: 应用过滤器
~
: 连接字符串和变量
.
: 获取对象属性
过滤器
abs(number)
: 返回绝对值
capitalize(s)
: 将字符串的第一个字母大写
title(s )
: 每个单词将以大写开头
lower(s )
: 全部字符小写
upper(s )
: 全部字符大写
default(value,default_value = u'',boolean = False )
: 定义某个变量的默认值
dictsort(value,case_sensitive = False,by ='key',reverse = False )
: 对字典进行排序
escape(s)
: 将字符串的值进行html转义
filesizeformat(value,binary = False )
: 将值格式化为KB,MB等形式
first(seq )
: 返回序列的第一项
last(seq )
: 返回序列的最后一项
length(obj)
: 返回对象的长度
float(值,默认= 0.0 )
: 转化为浮点数
int(值,默认= 0,基数= 10 )
: 转化为整数
format(值,* args,** kwargs )
: 在对象上应用python的格式化字符串
groupby(值,属性)
: 按属性对字典或者对象进行分组
join(value,d = u'',attribute = None )
: 连接可迭代对象
list(值)
: 将对象转化为一个列表
max(value,case_sensitive = False,attribute = None )
: 返回序列中最大值
min(value,case_sensitive = False,attribute = None )
: 返回序列中最小值
random(seq )
: 随机返回序列中的一个值
replace(s,old,new,count = None )
: 替换字符串
reverse(值)
: 反转对象
round(value,precision = 0,method ='common' )
: 对值进行四舍五入
safe(值)
: 对值不进行转义
slice(value,slices,fill_with = None )
: 切片
sort(value,reverse = False,case_sensitive = False,attribute = None )
: 对可迭代的对象进行正序排序
trim(值)
删除空格
模板继承
模板继承需要先定一个作为基准的父模板,其他模板继承此模板,再修改或者添加内容
extends 语句
此语句用来继承基础模板,用法如下:
{% extends 基准模板 %}
block 语句
此语句用来定义模板中需要修改的对象,用法如下:
{% block 变量 %}
语句
{% endblock %}
block语句允许多层嵌套,但是结束标签也需添加当前block的名称,具体如下
{% block 变量1 %}
语句1
{% block 变量2 %}
语句2
{% endblock 变量2 %}
{% endblock 变量1 %}
super 函数
此语句用来调用父模板之前的内容,并将之写入子模板中,用法如下
{{ super() }}
现在我们来看一个例子,首先定义一个base.html作为基准模板,然后定义一个new.html继承它
# base.html模板
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
{% block b %}
<h1>这是一个base模板中的内容h1>
{% endblock %}
body>
html>
替换base.html中的内容
# new.html模板
{% extends 'base.html' %}
{% block b %}
<h1>这是new中的内容h1>
{% endblock %}
使用super继承父模板中的内容
# new.html模板
{% extends 'base.html' %}
{% block b %}
{{ super() }}
<h1>这是new中的内容h1>
{% endblock %}
macro 宏
宏相当于变成语言中的函数,采用以下形式定义
{% macro 函数名() %}
语句
{% endmacro %}