python中的flask框架Jinja?模板入門教程
Flask 和 Django 附帶了強(qiáng)大的 Jinja 模板語(yǔ)言。
對(duì)于之前沒(méi)有接觸過(guò)模板語(yǔ)言的人來(lái)說(shuō),這類語(yǔ)言基本上就是包含一些變量,當(dāng)準(zhǔn)備渲染呈現(xiàn) HTML 時(shí),它們會(huì)被實(shí)際的值替換。
這些變量放在標(biāo)記或分隔符之前。例如:Jinja 模板使用 {% ... %} 表示循環(huán),{{ ... }} 表示一個(gè)表達(dá)式運(yùn)算結(jié)果返回。
Jinja 模板其實(shí)是 html 文件。一般情況下放在 Flask 工程的
/templates目錄下
1、快速體驗(yàn)
跑下面的各種 demo 之前,確保你已經(jīng)安裝了 Jinja (pip install jinja2)
>>> from jinja2 import Template
>>> t = Template("Hello {{ something }}!")
>>> t.render(something="World")
u'Hello World!'
>>> t = Template("My favorite numbers: {% for n in range(1,10) %}{{n}} " "{% endfor %}")
>>> t.render()
u'My favorite numbers: 1 2 3 4 5 6 7 8 9 '這個(gè) demo 展示了模板中的變量(表達(dá)式)是如何最終被替換和渲染的。
2、Flask 最小 DEMO
整個(gè)的參考代碼可以在這里獲得:HERE
不過(guò)博主建議按照下面步驟一步步來(lái):
1)安裝 flask
? pip install flask
2)創(chuàng)建工程目錄結(jié)構(gòu):
? mkdir flask_example ? cd flask_example ? mkdir templates ? cd .. ? touch run.py ? touch requirements.txt
3)編寫 run.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def template_test():
return render_template('template.html', my_string="Wheeeee!", my_list=[0,1,2,3,4,5])
if __name__ == '__main__':
app.run(debug=True)這里,我們創(chuàng)建了一個(gè) / 路由,當(dāng)我們?cè)L問(wèn)服務(wù)器根路由時(shí),會(huì)通過(guò) render_template 將 template.html 渲染,其中 my_string 和 my_list 就是準(zhǔn)備傳給模板的實(shí)際的值。
4)編寫 template.html 模板
在 templates 目錄下,創(chuàng)建一個(gè) template.html:
<!DOCTYPE html>
<html>
<head>
<title>Flask Template Example</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" media="screen">
<style type="text/css">
.container {
max-width: 500px;
padding-top: 100px;
}
</style>
</head>
<body>
<div class="container">
<p>My string: {{my_string}}</p>
<p>Value from the list: {{my_list[3]}}</p>
<p>Loop through the list:</p>
<ul>
{% for n in my_list %}
<li>{{n}}</li>
{% endfor %}
</ul>
</div>
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
</body>
</html>5)運(yùn)行觀察效果
? python run.py
效果如下:

可以看到,將模板中的 my_string、my_list[3] 替換掉了,并且用 for 循環(huán)語(yǔ)句,生成了一個(gè) list。
3、模板繼承
模板通常利用繼承,繼承包括定義所有后續(xù)子模板基本結(jié)構(gòu)的單個(gè)基礎(chǔ)模板。您可以使用標(biāo)記 {% extends %} 和 {% block %} 來(lái)實(shí)現(xiàn)繼承。
這樣做的用例很簡(jiǎn)單:隨著應(yīng)用程序的增長(zhǎng),以及您繼續(xù)添加新模板,您將需要保持公共代碼(如HTML導(dǎo)航欄、Javascript庫(kù)、CSS樣式表等)同步,這可能需要大量工作。使用繼承,我們可以將這些公共部分移動(dòng)到父/基模板,這樣我們就可以創(chuàng)建或編輯這樣的代碼一次,所有子模板都將繼承該代碼。
注意:您應(yīng)該總是盡可能多地向基本模板添加重復(fù)代碼,以節(jié)省將來(lái)的時(shí)間,這將遠(yuǎn)遠(yuǎn)超過(guò)初始時(shí)間投資。
讓我們給我們的 DEMO 增加模板:
1)創(chuàng)建基礎(chǔ)模板(保存為 layout.html)
<!DOCTYPE html>
<html>
<head>
<title>Flask Template Example</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" media="screen">
<style type="text/css">
.container {
max-width: 500px;
padding-top: 100px;
}
h2 {color: red;}
</style>
</head>
<body>
<div class="container">
<h2>This is part of my base template</h2>
<br>
{% block content %}{% endblock %}
<br>
<h2>This is part of my base template</h2>
</div>
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
</body>
</html>你注意到 {%block%} 標(biāo)記了嗎?這定義了子模板可以填充的塊或區(qū)域。此外,也可實(shí)現(xiàn)覆蓋的作用。
2)用模板更新 template.html:
{% extends "layout.html" %}
{% block content %}
<h3> This is the start of my child template</h3>
<br>
<p>My string: {{my_string}}</p>
<p>Value from the list: {{my_list[3]}}</p>
<p>Loop through the list:</p>
<ul>
{% for n in my_list %}
<li>{{n}}</li>
{% endfor %}
</ul>
<h3> This is the end of my child template</h3>
{% endblock %}這樣 layout.html 模板中的 content 塊就會(huì)被 template.html 中的新定義給替換掉,最終效果如下:

那么,我們就可以通過(guò)修改 layout.html 給其添加通用導(dǎo)航欄了:(將下列代碼插入到 layout.html 的 <body> 標(biāo)簽之后)
<nav class="navbar navbar-inverse" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">Jinja!</a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Link</a></li>
<li><a href="#">Link</a></li>
</ul>
<form class="navbar-form navbar-left" role="search">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Link</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>現(xiàn)在,從基礎(chǔ)擴(kuò)展的每個(gè)子模板都將具有相同的導(dǎo)航欄。借用Java哲學(xué)的一句話:"Write once, use anywhere."

4、Super Blocks
如果需要從基礎(chǔ)模板渲染塊,使用 super block:
{{ super() }}給基礎(chǔ)模板增加一個(gè)頁(yè)腳:
<body>
<div class="container">
...
<h2>This is part of my base template</h2>
<br>
<div class="footer">
{% block footer %}
Watch! This will be added to my base and child templates using the super powerful super block!
<br>
<br>
<br>
{% endblock %}
</div>
</div>
...此時(shí),我們可以給 template.html 增加 super block,從而實(shí)現(xiàn)子模板復(fù)用父模板中的塊:
{% extends "layout.html" %}
{% block content %}
<h3> This is the start of my child template</h3>
<br>
<p>My string: {{my_string}}</p>
<p>Value from the list: {{my_list[3]}}</p>
<p>Loop through the list:</p>
<ul>
{% for n in my_list %}
<li>{{n}}</li>
{% endfor %}
</ul>
<h3> This is the end of my child template</h3>
{% block footer %}
{{super()}}
{% endblock %}
{% endblock %}效果如下:

super block 用于模塊共享父模塊的 block,當(dāng)然還有一些高級(jí)玩法,比如下面的例子:
父模板:
{% block heading %}
<h1>{% block page %}{% endblock %} - Flask Super Example</h1>
{% endblock %}子模板:
{% block page %}Home{% endblock %}
{% block heading %}
{{ super() }}
{% endblock %}這樣當(dāng)訪問(wèn)子模塊時(shí),會(huì)拼接一個(gè) <h1>Home - Flask Super Example</h1> 字段。發(fā)現(xiàn)沒(méi),我們通過(guò)這樣的方法,實(shí)現(xiàn)了標(biāo)題的繼承(有一定的繼承,也有一定的子模塊自己的信息)。
回歸正軌,對(duì)于更新標(biāo)題,我們這里這樣設(shè)計(jì)(修改 template.html 中的兩行代碼)
{% block title %}{{title}}{% endblock %}
...
{% block page %}{{title}}{% endblock %}這樣我們可以通過(guò) python 進(jìn)來(lái)直接修改標(biāo)題了(修改 run.py):
@app.route("/")
def template_test():
return render_template(
'template.html', my_string="Wheeeee!",
my_list=[0,1,2,3,4,5], title="Home")5、Macros
在 Jinja 中,我們可以使用宏來(lái)抽象常用的代碼段,這些代碼段被反復(fù)使用以避免重復(fù)。例如,通常會(huì)在導(dǎo)航欄上突出顯示當(dāng)前頁(yè)面的鏈接(活動(dòng)鏈接)。否則,我們必須使用 if/elif/else 語(yǔ)句來(lái)確定活動(dòng)鏈接。使用宏,我們可以將這些代碼抽象成一個(gè)單獨(dú)的文件。
新增一個(gè) macros.html 文件:
{% macro nav_link(endpoint, name) %}
{% if request.endpoint.endswith(endpoint) %}
<li class="active"><a href="{{ url_for(endpoint) }}">{{name}}</a></li>
{% else %}
<li><a href="{{ url_for(endpoint) }}">{{name}}</a></li>
{% endif %}
{% endmacro %}這里,我們使用了 Flask 的 request object(Jinja 的默認(rèn)一部分),用來(lái)檢查請(qǐng)求端點(diǎn),然后將活動(dòng) class 分配給該端點(diǎn)。
使用基礎(chǔ)模板中的nav navbar nav類更新無(wú)序列表:
<ul class="nav navbar-nav">
{{ nav_link('home', 'Home') }}
{{ nav_link('about', 'About') }}
{{ nav_link('contact', 'Contact Us') }}
</ul>此外,請(qǐng)確保在模板頂部添加導(dǎo)入:{% from "macros.html" import nav_link with context %}
最后,讓我們向控制器添加三個(gè)新端點(diǎn):
@app.route("/home")
def home():
return render_template(
'template.html', my_string="Wheeeee!",
my_list=[0,1,2,3,4,5], title="Home")
@app.route("/about")
def about():
return render_template(
'template.html', my_string="Wheeeee!",
my_list=[0,1,2,3,4,5], title="About")
@app.route("/contact")
def contact():
return render_template(
'template.html', my_string="Wheeeee!",
my_list=[0,1,2,3,4,5], title="Contact Us")刷新頁(yè)面。測(cè)試頂部的鏈接。當(dāng)前頁(yè)面是否突出顯示?(每次點(diǎn)擊 Home, About, Contact Us,瀏覽器會(huì)自動(dòng)跳轉(zhuǎn)到對(duì)應(yīng)的 url,并加載頁(yè)面)
6、自定義過(guò)濾器
Jinja 使用過(guò)濾器修改變量,主要用于格式化目的。
這有個(gè)例子;
{{ num | round }}這將使 num 變量四舍五入。因此,如果我們將參數(shù) num=46.99 傳遞到模板中,那么將輸出47.0。(把大括號(hào)中的語(yǔ)句當(dāng)做 shell,就明白了,豎線是傳遞作用,round是個(gè)過(guò)濾器,這里是所有的過(guò)濾器)
再來(lái)個(gè)例子:
{{ list|join(', ') }}可以給 list 數(shù)組中的變量加個(gè)逗號(hào)。
其實(shí),除了自帶的過(guò)濾器,我們也可以自定義:
1)在 run.py 的所有函數(shù)前增加 app = Flask(__name__) 用于創(chuàng)建一個(gè) app
2)增加一個(gè) datetimefilter 函數(shù),并將其注冊(cè)到 app 的過(guò)濾器
@app.template_filter() # 聲明,這是個(gè)過(guò)濾器
def datetimefilter(value, format='%Y/%m/%d %H:%M'):
"""Convert a datetime to a different format."""
return value.strftime(format)
app.jinja_env.filters['datetimefilter'] = datetimefilter3)這樣,我們?cè)谧幽0逯胁迦肴缦麓a:
<h4>Current date/time: {{ current_time | datetimefilter }}</h4>4)最后,只要在 python 中將時(shí)間傳入模板即可:
current_time = datetime.datetime.now()
5)效果如下:

7、結(jié)論
這樣,就送大家快速入門了 Jinja,源碼:https://github.com/mjhea0/thinkful-mentor/tree/master/python/jinja/flask_example
參考鏈接
[1]. 本文源碼
[2]. Primer on Jinja Templating(本文翻譯并參考這篇)
[3]. Flask 官方文檔
[4]. 真正搞明白Python中Django和Flask框架的區(qū)別
[5]. Flask 主頁(yè)
[6]. 一個(gè) Soft UI Dashboard - Free Jinja Template
[7]. Appseed 這個(gè)網(wǎng)站有很多 Flask 模板
[8]. Nginx 服務(wù)器 SSL 證書安裝部署
[9]. python django web 開發(fā) —— 15分鐘送到會(huì)用(只能送你到這了)
到此這篇關(guān)于python中的flask框架Jinja 模板入門的文章就介紹到這了,更多相關(guān)python flask Jinja 模板內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python判斷文件是否存在,不存在就創(chuàng)建一個(gè)的實(shí)例
今天小編就為大家分享一篇python判斷文件是否存在,不存在就創(chuàng)建一個(gè)的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-02-02
升級(jí)keras解決load_weights()中的未定義skip_mismatch關(guān)鍵字問(wèn)題
這篇文章主要介紹了升級(jí)keras解決load_weights()中的未定義skip_mismatch關(guān)鍵字問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-06-06
Python OpenCV對(duì)圖像像素進(jìn)行操作
大家好,本篇文章主要講的是Python OpenCV對(duì)圖像像素進(jìn)行操作,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽2022-01-01
python報(bào)錯(cuò): ''list'' object has no attribute ''shape''的解決
這篇文章主要介紹了python報(bào)錯(cuò): 'list' object has no attribute 'shape'的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07
下載與當(dāng)前Chrome對(duì)應(yīng)的chromedriver.exe(用于python+selenium)
這篇文章主要介紹了下載與當(dāng)前Chrome對(duì)應(yīng)的chromedriver.exe(用于python+selenium),本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-01-01
python寫一個(gè)隨機(jī)點(diǎn)名軟件的實(shí)例
今天小編就為大家分享一篇python寫一個(gè)隨機(jī)點(diǎn)名軟件的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-11-11
python實(shí)現(xiàn)web方式logview的方法
這篇文章主要介紹了python實(shí)現(xiàn)web方式logview的方法,涉及Python基于web模塊操作Linux命令的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08
YOLOv5中SPP/SPPF結(jié)構(gòu)源碼詳析(內(nèi)含注釋分析)
其實(shí)關(guān)于YOLOv5的網(wǎng)絡(luò)結(jié)構(gòu)其實(shí)網(wǎng)上相關(guān)的講解已經(jīng)有很多了,但是覺(jué)著還是有必要再給大家介紹下,下面這篇文章主要給大家介紹了關(guān)于YOLOv5中SPP/SPPF結(jié)構(gòu)源碼的相關(guān)資料,需要的朋友可以參考下2022-05-05

