外观
模板进阶知识
模板上下文
Flask有上下文,Jinja2也有上下文。
通常情况下,在渲染模板时可以调用render_template()传入参数。此外,还可以使用set标签在模板中定义变量,如:
{% set navigation = [('/', 'Home'%), ('/about', 'About')] %}也可以将一部分模板变量数据定义为变量,使用set和endset标签声明开始和结束。例如:
{% set navigation %}
<li><a href='/'>首页</a></li>
<li><a href='/about'>关于</a></li>
{% endset %}Flask在模板上下文中也定义了一些内置对象,可以在模板中直接使用。这些内置对象如下表所示:
| 属性 | 说明 |
|---|---|
| config | 当前的配置对象 |
| request | 当前的请求对象,在已激活的请求环境中使用 |
| session | 当前的会话对象,在已激活的请求环境中使用 |
| g | 与请求绑定的全局变量,在已激活的请求环境下可用 |
下面通过一个实例介绍如何使用Session。
# run.py
from flask import Flask, render_template, request, session
app = Flask(__name__)
app.config['SECRET_KEY'] = 'qi'
@app.route('/')
def index():
return render_template('index.html')
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
user = request.form['user']
password = request.form['password']
if user == 'qi' and password == '123456':
session['user'] = user
return '登录成功'
else:
return '登录失败'
return render_template('login.html')
@app.route('/logout')
def logout():
session.clear()
return '退出成功'
if __name__ == '__main__':
app.run()<!-- login.html -->
<!doctype html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>登录</title>
</head>
<body>
<form action="" method="post">
<label for="user">用户名:</label><input type="text" id="user" name="user"><br/>
<label for="password">密码:</label><input type="password" id="password" name="password"><br/>
<input type="submit" value="登录">
</form>
</body>
</html><!-- index.html -->
<!doctype html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>首页</title>
</head>
<body>
{% if session['user'] == 'qi' %}
欢迎{{ session['user'] }}登录
{% else %}
请先登录
{% endif %}
</body>
</html>模板过滤器
内置过滤器
在前面已经介绍了一些简单的过滤器,如safe、trim等,Jinja2中还有很多过滤器,它们的功能如下表:
| 过滤器 | 说明 |
|---|---|
| default(value, default_value='u', boolean=False) | 设置默认值,默认值作为参数传入,别名为d |
| escape(e) | 转义HTML文本,别名为e |
| fisrt(q) | 返回序列的第一个元素 |
| last(q) | 返回序列的最后一个元素 |
| length(object) | 返回变量的长度 |
| random(q) | 返回序列中的随机元素 |
| max(value, case_sensitive=False, attribute=None) | 返回序列中的最大值 |
| min(value, case_sensitive=False, attribute=None) | 返回序列中的最小值 |
| unique(value, case_sensitive=False, attribute=None) | 返回序列中不重复的值 |
| wordcount(s) | 计算单词数量 |
| tojson | 将变量值转换为JSON格式 |
| truncate(s, length=255, killwords=False, end='...', leeway=None) | 截取字符串,可用于显示文章摘要,length参数设置截止的长度,killwords参数设置是否截取单词,end参数设置结尾的符号 |
如,模板中的Article.title变量如下:
Article.title='你好,这里是棋,很高兴认识你。目前我是一名大二学生,在努力学习后端,励志做一名优秀的后端工程师。我非常喜欢计算机,只要有我感兴趣的东西我都会学习下去。目前已经独立或合作做了很多大小项目,并且有很多收获。未来的路还有很长要走,离毕业还有很久,我会继续努力下去。'使用truncate()方法可以截取Article.title变量,示例代码如下:
{{ Article.title|truncate(10) }}运行结果如下:
你好,这里是棋...自定义过滤器
除此之外,还可以自定义过滤器。有两种方法可以自定义过滤器:使用Flask应用对象的add_template_filter方法、一种是应用app.template_filter装饰器来实现自定义过滤器。
下面给出两个例子:
- 使用add_template_filter方法
# run.py
from flask import Flask, render_template
app = Flask(__name__)
content = '你好,这里是棋,很高兴认识你。目前我是一名大二学生,在努力学习后端,励志做一名优秀的后端工程师。我非常喜欢计算机,只要有我感兴趣的东西我都会学习下去。目前已经独立或合作做了很多大小项目,并且有很多收获。未来的路还有很长要走,离毕业还有很久,我会继续努力下去。'
def count(s):
return len(s)
app.add_template_filter('count', count)
@app.route('/')
def index():
return render_template('index.html', content=content)
if __name__ == '__main__':
app.run()<!-- index.html -->
<!doctype html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>首页</title>
</head>
<body>
全文字数:
{{ content|count }}
<hr/>
{{ content }}
</body>
</html>- 使用app.template_filter装饰器
只需要将上方的Python代码改为如下形式:
from flask import Flask, render_template
app = Flask(__name__)
content = '你好,这里是棋,很高兴认识你。目前我是一名大二学生,在努力学习后端,励志做一名优秀的后端工程师。我非常喜欢计算机,只要有我感兴趣的东西我都会学习下去。目前已经独立或合作做了很多大小项目,并且有很多收获。未来的路还有很长要走,离毕业还有很久,我会继续努力下去。'
@app.template_filter
def count(s):
return len(s)
@app.route('/')
def index():
return render_template('index.html', content=content)
if __name__ == '__main__':
app.run()这两段代码的运行结果相同,都是先显示字数,然后显示全文内容。