jinja2
字符串传值
方式一
方式二
模版中使用url_for
过滤器
自定义过滤器
条件判断
for循环
方式一
方式二
宏
宏的基本使用
导入宏
导入别的目录的宏
inclue
extends继承
set和with语句
加载静态文件
jinja2
在之前的章节中,视图函数只是直接返回文本,而在实际生产环境中其实很少这样用,因为实际的页面大多是带有样式和复杂逻辑的html代码,这可以让浏览器渲染出非常漂亮的页面。目前市面上有非常多的模板系统,其中最知名最好用的就是Jinja2,Jinja是日本寺庙的意思,并且寺庙的英文是temple和模板的英文template的发音类似。Jinja2是默认的仿Django模板的一个模板引擎,由Flask的作者开发。它速度快,被广泛使用,并且提供了可选的沙箱模板来保证执行环境的安全,让前端开发者和后端开发者工作分离。减少Flask项目代码的耦合性,页面逻辑放在模板中,业务逻辑放在视图函数中,将页面逻辑和业务逻辑解耦有利于代码的维护。提供了控制语句、继承等高级功能,减少开发的复杂度;
Flask渲染Jinja模板,通过render_template方法即可;
向模版传参有两种方式,第一种是用关键字参数的形式传递,第二种是直接传递一个字典;
字符串传值
从后端传递一个变量,并且在template中引用,然后在render的时候进行变量替换;
方式一
return render_template('home.html',username=username) # 等价于 return render_template('home.html', **data)
<p style="text-align: center;font-size: 20px;color: red">Hi,{{ username }}!</p>
方式二
传递字典,在模版中用对象的方式等三种取值方式;
data={
'username':'cce'
}
return render_template('home.html', data=data)
<p style="text-align: center;font-size: 20px;color: red">Hi,{{ data.username }} {{ data['username'] }} {{ data.get('username') }}!!</p>
模版中使用url_for
直接在模版中使用url_for,拿到登录的url;
@app.route('/')
def home():
data = {
'username': 'cce'
}
return render_template('home.html', data=data)
@app.route('/account/login')
def login():
return '登录成功'
<p>登录的URL为:{{ url_for('login',next='/') }}</p>
<a href="{{ url_for('login') }}">登录</a>
过滤器
过滤器是通过管道符(|)进行使用的,例如:{{ name|length }},将返回name的长度,过滤器相当于是一个函数,把当前的变量传入到过滤器中,然后过滤器根据自己的功能再返回对应的值,之后再将结果渲染到页面中;
abs(value):返回一个数值的绝对值。示例:-1|abs
default(value,default_value,boolean=false):如果当前变量没有值,则会使用参数中的值来代替。示例:name|default('xiaotuo')——如果name不存在,则会使用xiaotuo来替代。boolean=False默认是在只有这个变量为undefined的时候才会使用default中的值,如果想使用python的形式判断是否为false,则可以传递boolean=true。也可以使用or来替换。
escape(value)或e:转义字符,会将<、>等符号转义成HTML中的符号。示例:content|escape或content|e。
first(value):返回一个序列的第一个元素。示例:names|first
format(value,*arags,**kwargs):格式化字符串。比如:
{{ "%s" - "%s"|format('Hello?',"Foo!") }}
将输出:Helloo? - Foo!
last(value):返回一个序列的最后一个元素。示例:names|last。
length(value):返回一个序列或者字典的长度。示例:names|length。
join(value,d=u''):将一个序列用d这个参数的值拼接成字符串。
safe(value):如果开启了全局转义,那么safe过滤器会将变量关掉转义。示例:content_html|safe。
int(value):将值转换为int类型。
float(value):将值转换为float类型。
lower(value):将字符串转换为小写。
upper(value):将字符串转换为小写。
replace(value,old,new): 替换将old替换为new的字符串。
truncate(value,length=255,killwords=False):截取length长度的字符串。
striptags(value):删除字符串中所有的HTML标签,如果出现多个空格,将替换成一个空格。
trim:截取字符串前面和后面的空白字符。
string(value):将变量转换成字符串。
wordcount(s):计算一个长字符串中单词的个数。
自定义过滤器
当jinja2内置的过滤不能够满足我们,那么我们就可以自定义过滤器了,示例如下;
# 将过滤器加入jinja2模版
@app.template_filter('length_3') # 指明过滤器的名字
# 定义过滤器
def length_3(value):
if len(value) < 3:
return value
return value[0:3]
<p>{{ '我只留三个字符' |length_3 }}</p>
条件判断
@app.route('/')
def home():
data = {
'name':'cce'
}
return render_template('home.html', **data)
<body>
{% if name == 'cce' %}
<p>cce</p>
{% elif name == 'cfj' %}
<p>cfj</p>
{% else %}
<p>None</p>
{% endif %}
</body>
for循环
loop.index:当前迭代的索引,从1开始;
loop.index0:当前迭代的索引,从0开始;
loop.first:是否是第一次迭代,Bool值;
loop.last:是否是最后一次迭代,Bool值;
loop.length:返回序列的长度;
方式一
@app.route('/')
def home():
data=['cce1','cce2','cce3']
return render_template('home.html', data=data)
<table border="1px" style="border-collapse:collapse;">
{% for datum in data %}
<tr>
<td>{{ datum }}</td>
<td>{{ loop.index }}</td>
<td>{{ loop.first }}</td>
<td>{{ loop.last }}</td>
<td>{{ loop.length }}</td>
<td>{{ loop.index0 }}</td>
</tr>
{% endfor %}
</table>
方式二
@app.route('/')
def home():
data = [
{'name':'cce','age':18},
{'name':'cfj','age':10},
]
return render_template('home.html', data=data)
<table border="1px" style="border-collapse:collapse;">
{% for data in data %}
<p>{{ data.get('name') }}</p>
<p>{{ data.get('age') }}</p>
{% endfor %}
</table>
宏
模版中的宏跟python中的函数类似,可以传递参数,但是不能有返回值,可以将一些经常用到的代码片段放到宏中,然后把一些不固定的值取出,当作一个变量来进行传递;
宏的基本使用
<table border="1px" style="border-collapse:collapse;">
# 定义宏,可以设定默认值
{% macro macro_name(name,age,city='Wuhan') %}
<p>{{ name }}</p>
<p>{{ age }}</p>
<p>{{ city }}</p>
{% endmacro %}
# 调用宏
{{ macro_name('cce',18) }}
</table>
导入宏
在别的项目文件中导入宏,可以使用as来对宏的名字做别名,如果当前html和宏的文件不再同一个文件夹下面,那么可以使用../的方式导入;
// macros.html
{% macro macro_name(name,age,city='Wuhan') %}
<p>{{ name }}</p>
<p>{{ age }}</p>
<p>{{ city }}</p>
{% endmacro %}
{% from 'macros.html' import macro_name as macros %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta charset="UTF-8">
<link rel="icon" href="http://jenkins.doorta.com/static/92c9360d/images/headshot.png">
<title>home</title>
</head>
<body>
<table border="1px" style="border-collapse:collapse;">
{{ macros('cce',18) }}
</table>
</body>
</html>
导入别的目录的宏
如果我们在宏中也想使用当前模版中的变量,那么我们可以使用with context将当前环境的所有变量全部传递给宏;
@app.route('/')
def home():
data = [
{'name':'cce','age':18},
{'name':'cfj','age':10},
]
return render_template('home.html', data=data)
// macros.html
{% macro macro_name(name,age,city='Wuhan') %}
<p>{{ name }}</p>
<p>{{ age }}</p>
<p>{{ city }}</p>
<p>{{ data }}</p>
{% endmacro %}
// index.html
{% import 'macros.html' as macros with context %} # 导入宏
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta charset="UTF-8">
<link rel="icon" href="http://jenkins.doorta.com/static/92c9360d/images/headshot.png">
<title>home</title>
</head>
<body>
<table border="1px" style="border-collapse:collapse;">
{{ macros.macro_name('cce',18) }}
</table>
</body>
</html>
inclue
如果我们想要一个html文件里面所有代码重复利用,那么我们可以使用inclued来实现,注意inclued可以直接使用父模版文件的变量;
@app.route('/')
def home():
return render_template('home.html', name='cce') # 传递一个变量
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta charset="UTF-8">
<link rel="icon" href="http://jenkins.doorta.com/static/92c9360d/images/headshot.png">
<title>home</title>
</head>
<body>
{% include 'inclues.html' %}
</body>
</html>
// inclued.html
<p>这里的inclued,这里是变量{{ cce }}</p>
extends继承
模版继承可以把一些公用的代码单独抽取出来放到一个父模版中,以后子模版直接继承就可以使用,这样代码可以重复性使用,并且修改也比较方便,如果在block里面还是引用引用已经使用的blockk里面其他的block那么可以使用{{ self.block_name() }}来引用;
// base.html 父模版
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta charset="UTF-8">
<link rel="icon" href="http://jenkins.doorta.com/static/92c9360d/images/headshot.png">
{% block title %}
{% endblock %}
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>
// index.html 子模版
{% extends 'base.html' %} # 这一段的内容主要是将base.html里面文件全部导入进来,继承base.html,非block的内容
{% block title %} # 这段内容主要是对block里面的内容进行赋值
<title>cce</title>
{% endblock %}
{% block body %} # 这段内容主要是对block里面的内容进行赋值
{{ self.title() }} // 引用上面的block
<p>1</p>
{% endblock %}
set和with语句
set的主要作用和python的变量赋值相似,只要使用set设置了变量,那么在当前模版文件下,可以全局引用;
<body>
{% set username='cce' %}
<p>这里是set的值:{{ username }}</p>
</body>
with的主要作用和python的变量赋值相似,只要使用set设置了变量,那么在当前模版文件下,可以局部引用,局部就是在with代码块内部;
<body>
{% with username = 'cce' %}
{{ username }}
{% endwith %}
</body>
加载静态文件
默认是当前项目目录下面的static,如果有做修改可以在创建flask实例的时候指明,static_folder静态文件的路径,以当前项目为基准,static_url_path静态文件的访问路径;
app = Flask(__name__,static_folder='static',static_url_path='/static')
// 引用方式一
<link rel="stylesheet" href="/cce/cce.css">
// 引用方式二
<link rel="stylesheet" href="{{ url_for('static',filename="cce.css") }}">
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved