做為python web開發領域的一員,flask跟Django在很多地方用法以都是相似的,比如flask的模板
模板就是服務器端的頁面,在模板中可以使用服務端的語法進行輸出控制
1.模板的工作原理
在視圖函數中,通過render_template方法返回一個頁面,然后通過Jinja2語法來進行渲染
簡單來說,就是把服務器端的html頁面解釋成用戶看到的頁面,而視圖函數是通過上下文對象來進行變量的傳遞
在項目開發中,視圖函數經常會把一些服務器處理完成的變量傳遞給前端頁面進行渲染,
比如在下面的例子中,由render_template返回html頁面時,攜帶一些變量數據給Jinja2語法進行渲染
from flask import Flask, render_template
app = Flask(__name__)
app.debug = True
@app.route('/')
def hello_world():
return 'Hello World!'
@app.route('/detail')
def detail():
message = {
'name':'jack',
'text':'傑克'
}
return render_template('detail.html',info=message)
if __name__ == '__main__':
app.run(debug=True)
前端頁面detail.html內容為:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>{{ info.name }}詳細信息</h1>
<div>
我的名字叫:{{ info.text }}
</div>
</body>
</html>
啟動項目,瀏覽器打開http://127.0.0.1:5000/detail頁面,前端頁面渲染后效果為:

那么此時,如果后台返回給前端的變量為一段html代碼,返回給前端經過Jinja2語法渲染后,效果會是怎么樣的呢??
2.Jinja2語法安全機制
修改message變量,然后由render_template返回
@app.route('/detail')
def detail():
message = {
'name':'jack',
'text':'<h2>傑克</h2>'
}
return render_template('detail.html',info=message)
前端頁面不變,刷新瀏覽器,效果如下

可以看到,返回的變量中包含html代碼,但是Jinja2語法並沒有對這一小段代碼進行渲染,而是直接顯示了出來
實際上這是為了安全,因為如果后台返回的html代碼中包含惡意的js代碼,如果直接就渲染了,會造成站點被攻擊。
那如果我就是想渲染后台返回給前端的HTML代碼,那應該怎么辦呢
在flask中,如果確認后台返回給前端進行渲染的變量中包含的HTML代碼是安全的,則可以使用一些方法來對這段HTML代碼也進行渲染
方法一:autoescape 關閉安全機制
這種方法與Django的模板語法相同
后台代碼不變,修改前端detail.html代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% autoescape false %}
<h1>{{ info.name }}詳細信息</h1>
<div>
我的名字叫:{{ info.text }}
</div>
{% endautoescape %}
</body>
</html>
此時,再次刷新頁面,查看效果

方法二,調用Jinja2的safe過濾器
如果覺得第一種方法有點麻煩,可以使用第二種方法
后台代碼不變,同樣修改detail.html頁面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>{{ info.name }}詳細信息</h1>
<div>
我的名字叫:{{ info.text | safe }}
</div>
</body>
</html>
此時,再次刷新頁面,效果跟第一種方法一樣
在flask中,Jinja2語法提供了很多過濾器,可以在下面的地址進行查找
http://jinja.pocoo.org/docs/dev/templates/
3.自定義過濾器
在寫文章或博客的時候,很多時候都會用到Markdown語法
在flask的Jinja2語法中,並沒有標准的Markdown語法過濾器,此時可以使用擴展來自定義Markdown語法過濾器
修改flask項目文件
from flask import Flask, render_template
app = Flask(__name__)
app.debug = True
@app.route('/')
def hello_world():
return 'Hello World!'
@app.route('/detail')
def detail():
message = {
'name':'jack',
'text':'<h2>傑克</h2>'
}
return render_template('detail.html',info=message,markdown='## Markdown編輯器<br>`注釋`')
@app.template_filter('md')
def markdown_html(txt):
from markdown import markdown
return markdown(txt)
if __name__ == '__main__':
app.run(debug=True)
修改detail.html前端頁面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>{{ info.name }}詳細信息</h1>
<div>
我的名字叫:{{ info.text | safe }}
{{ markdown | md | safe }}
</div>
</body>
</html>
刷新瀏覽器,查看效果

在實際開發中,后台向模板中傳遞的不只有變量和filter,還可能會向前端傳遞一個方法,此時可以使用flask的上下文來實現
修改flask項目文件
#-*- coding: utf-8 -*-
from flask import Flask, render_template
app = Flask(__name__)
app.debug = True
@app.route('/')
def hello_world():
return 'Hello World!'
def read_md(filename):
from functools import reduce
with open(filename,encoding='utf-8') as md_file:
content = reduce(lambda x,y:x + y, md_file.readlines())
return content
@app.context_processor
def methods():
return dict(read_md=read_md)
@app.route('/detail')
def detail():
message = {
'name':'jack',
'text':'<h2>傑克</h2>'
}
return render_template('detail.html',info=message,markdown='## Markdown')
@app.template_filter('md')
def markdown_html(txt):
from markdown import markdown
return markdown(txt)
if __name__ == '__main__':
app.run(debug=True)
如果想在Jinja2語法中調用后台定義的某個函數時,比如在這個例子中,前端頁面中調用后台定義的read_md方法來處理某個Markdown格式的文件時,可以使用context_processor上下文處理器。
在項目中應用了context_processor時,flask會把context_processor裝飾的方法注冊到Jinja2模板語法中來,這樣就可以在Jinja2語法中調用后台的方法了
用context_processor裝飾的后台方法可以在前端所有的Jinja2語法中調用
修改前端頁面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>{{ info.name }}詳細信息</h1>
<div>
我的名字叫:{{ info.text | safe }}
{{ markdown | md | safe }}
{{ read_md('editor.md') |md| safe}}
</div>
</body>
</html>
刷新瀏覽器,查看效果

使用過濾器和context_processor配置一起使用時,可以很靈活的進行頁面的渲染
