一、认识模板以及模板引擎
在 MTV 模型中,T 既 Templates 模板,模板是一个包含响应文本的文件(通常是html文件),该文件中允许包含 ”占位变量“ 来表示动态的内容,其具体值会在请求的响应中给出。”占位变量“ 最终会被真实的值所替换。模板解析成相应的字符串,这一过程称为 ”渲染“。Flask 框架使用的是 Jinja2 模板引擎。
模板引擎的基础语法主要包含了变量、标签和过滤器的使用,以及模板的抽象即通过继承和包含来减少重复代码,除此之外还有包含了一些全局函数等。
使用 PyCharm 创建新的项目 flask-templates。
在启动配置中开启 Debug 模式。
在 templates 文件夹下新建一个 index.html 模板,在 app.py 中新增视图函数 show_html,该函数返回这个 html 页面。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"/> <title>Index</title> </head> <body> <h1>Hallo,This is Index!</h1> </body> </html> 复制代码
from flask import render_template @app.route('/index') def show_html(): return render_template('index.html') 复制代码
启动 Flask 应用,在浏览器输入 http://127.0.0.1:5000/index
页面被成功渲染,show_html 视图函数中的 render_template 函数会从磁盘中读取 HTML 模板中的字符串,并且将满足特定规则的变量或者内容替换为具体的值,最后再发送给浏览器,展示出 HTML 页面。
如果不使用 render_template 函数渲染模板,可以直接通过读取模板中的内容返回给浏览器,浏览器也会解析 HTML 代码。
@app.route('/index') def show_html(): html = os.path.join(os.getcwd(), 'templates', 'index.html') # 读取html中的内容 with open(html, 'r') as h: context = h.read() return context 复制代码
保存内容,浏览器中访问 http://127.0.0.1:5000/index
效果与使用 render_template 函数一致。
如果模板中有需要动态替换的变量,比如模板能够实时显示当前当前时间,这就需要先在模板中进行占位,我们约定通过 {{}}
包裹的字符都是变量,在响应时需要动态替换。
在 index.html 中增加内容。
<h2>Now is : {{ now }}</h2> 复制代码
修改 show_html 视图函数,将 {{now}}
替换为动态的时间。
from flask import Flask, render_template import os import datetime @app.route('/index') def show_html(): html = os.path.join(os.getcwd(), 'templates', 'index.html') # 当前时间 now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') # 读取html中的内容 with open(html, 'r') as h: context = h.read() # 变量替换 context = context.replace('{{ now }}', now) return context 复制代码
在浏览器中访问 /index
页面中展现出当前时间,此时刷新页面,页面中显示的时间会与当前时间保持一致。
当模板中包含了条件判断等逻辑,这就会导致视图函数越来越复杂,所以就有了模板的概念,并且这也会导致试图函数中包含很多公共代码,为了方便维护推荐使用 Jinja2 模板模板引擎。
二、Jinja2模板引擎
Jinja2 模板引擎
Flask 使用 Jinja2,需要单独进行安装。
pip3 install Jinja2 复制代码
Flask 类的 __init__
构造函数中指定了默认的模板目录项目根路径下的 templates
文件夹。
template_folder="templates", 复制代码
当然也可以在实例化 Flask 对象时指定自定义的模板目录。
app = Flask(__name__, template_folder="temps") 复制代码
渲染函数 render_template 和 render_template_string
render_template 函数可以将 xml 或者 html 进行转义,render_template_string 可以将字符串进行转义。
在 app.py 中新增两个视图函数,分别使用了 render_template 函数和render_template_string 函数渲染视图函数返回的内容。
@app.route('/render') def diff_render(): return render_template('index.html') @app.route('/render_str') def diff_render_str(): return render_template_string('index.html') 复制代码
浏览器访问 */render *
浏览器访问 render_str
两个视图函数返回的内容都是 index.html
页面,但是 render_template 函数将同名的模板 index.html 页面解析出来,而 render_template_string 则直接返回了字符串 index.html
。
转义
转义就是将特殊字符显示出来,比如在页面中显示一段 html 代码,就需要使用到转义。
转义有两种方式,第一种是通过转义字符代替特殊字符。
在 index.html 的 body 标签内增加内容
<h2>下面是一段要在页面中显示的超链接HTML代码</h2> <a href="#">点击</a> 复制代码
增加视图函数 transfer
@app.route('/transfer') def transfer(): return render_template('index.html') 复制代码
浏览器访问 http://127.0.0.1:5000/transfer
超链接 HTML 没有显示出来,而是被转义成了 HTML。
使用转义字符代替特殊字符,常用的转义字符有:
- ":"
- 空格:
- ¥:¥
- <:<
- >: >
修改 index.html 的内容
<h2>下面是一段要在页面中显示的超链接HTML代码</h2> <a href="#">点击</a> 复制代码
再次访问 /transfer
超链接代码被展示出来了。
第二种方式是通过模板中的 {% autoescape %}
来设置是否转义,默认模板是开启转义的,在 index.html 中增加代码。
<!--false表示关闭自动转义,默认时开启的--> {% autoescape false %} {{ info }} {% endautoescape %} 复制代码
在视图函数中返回一段HTML代码
@app.route('/transfer') def transfer(): info = "<a href='#'>超链接</a>" return render_template('index.html', info=info) 复制代码
使用 autoescape 时一定要注意关闭,并且 autoescape 设置只对返回变量包含 html 代码时有效。
模板中的全局对象
模板中包含了以下几个全局对象,可以直接使用:
- config:Flask的配置信息对象
- request:请求对象
- response:响应对象
- g:请求相关的全局变量
新增一个 object.html 模板,在该模板中使用全局变量占位。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"/> <title>Global Object</title> </head> <body> <h2>Flask的配置信息对象</h2> <p>config: {{ config }}</p> <h2>Flask请求对象</h2> <p>request: {{ request }}</p> </body> </html> 复制代码
增加一个视图函数,返回 object.html 页面
@app.route('/object') def object(): return render_template('object.html') 复制代码
浏览器访问 http://127.0.0.1:5000/object
g 是请求相关的全局对象,可以在 g 对象中设置一些全局变量,可以在所有请求中使用,可以在钩子函数中进行 g 对象属性的设置,在其他视图函数或者模板中获取 g 对象中的属性。
增加一个钩子函数,设置 g 对象的属性及属性值
from flask import g @app.before_first_request def before_first_request(): g.global_user = 'Tony Stark' 复制代码
在 object.html 中增加内容,获取 g 对象及 g 对象在钩子函数中设置的属性值。
<h2>g对象</h2> <p>g: {{ g }}</p> <p>g.global_user: {{ g.global_user }}</p> 复制代码