Jinja2是用純Python編寫的模闆引擎。 它提供了受Django啟發的非XML文法,但支援内聯表達式和可選的沙盒環境。 除了是易于使用的獨立模闆引擎之外,它很小但是很快。 Flask是基于Python的微型Web架構,可讓您快速有效地編寫Web應用程式。
在這個由三部分組成的系列文章中,我将從Flask的角度開始介紹Jinja2的基礎模闆。 在本系列的後續部分中,我将介紹進階模闆主題,同時學習如何在子產品化和可擴充設計的基于Flask的應用程式中布局模闆。
我假設您對使用Flask和環境設定最佳實踐有基本的了解,并在開發Python應用程式時遵循使用virtualenv 。
安裝套件
Flask随Jinja2一起打包,是以我們隻需要安裝Flask。 對于本系列,我建議使用Flask的開發版本,該版本包括許多其他功能中的更穩定的指令行支援以及對Flask的總體改進。
pip install https://github.com/mitsuhiko/flask/tarball/master
需要模闆引擎嗎?
在Flask中,我們可以編寫完整的Web應用程式,而無需任何第三方模闆引擎。 讓我們看看下面的一個小型
Hello World
應用程式:
from flask import Flask
app = Flask(__name__)
@app.route('/')
@app.route('/hello')
@app.route('/hello/<user>')
def hello_world(user=None):
user = user or 'Shalabh'
return '''
<html>
<head>
<title>Templating in Flask</title>
</head>
<body>
<h1>Hello %s!</h1>
<p>Welcome to the world of Flask!</p>
</body>
</html>''' % user
if __name__ == '__main__':
app.run()
顯然,在HTML,CSS和JS代碼成千上萬行的真實Web應用程式中,上述編寫應用程式的模式是不可行的。 在這裡,模闆可以節省我們的時間,因為我們可以通過使模闆分開來構造視圖代碼。 Flask預設情況下提供對Jinja2的支援,但也可以使用任何其他模闆引擎。
布置模闆
預設情況下,Flask希望将模闆放置在應用程式根級别的名為
templates
的檔案夾中。 然後Flask通過使該檔案夾可用于
render_template()
方法來自動讀取内容。 我将通過重組上面顯示的瑣碎的
Hello World
應用程式來示範相同的内容。
應用程式結構如下所示。
flask_app/
my_app.py
templates/
- index.html
應用本身
flask_app / my_app.py
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/')
@app.route('/hello')
@app.route('/hello/<user>')
def hello_world(user=None):
user = user or 'Shalabh'
return render_template('index.html', user=user)
flask_app / templates / index.html
<html>
<head>
<title>Templating in Flask</title>
</head>
<body>
<h1>Hello {{ user }}!</h1>
<p>Welcome to the world of Flask!</p>
</body>
</html>
要運作該應用程式,隻需在指令行上執行以下指令:
flask --app=my_app run
在浏覽器中打開http://127.0.0.1:5000/以檢視實際應用程式。 如果使用http://127.0.0.1:5000/hello ,結果也将相同。
嘗試打開以您的名字作為最後一部分的URL。 是以,如果您的名字叫John,則URL為http://127.0.0.1:5000/hello/John 。 現在頁面看起來像這樣:
很簡單,在
hello_world
方法中,從請求中擷取
hello
之後的URL的最後一部分,然後傳遞給使用
render_template()
呈現的模闆的上下文。 然後,使用Jinja2占位符
{{ user }}
從模闆上下文中解析此值。 此占位符根據模闆上下文評估放置在其中的所有表達式。
了解模闆中的塊和繼承
通常,任何Web應用程式都會有許多彼此不同的網頁。 整個站點中幾乎所有頁面中的頁眉和頁腳等代碼塊都相同。 同樣,菜單也保持不變。 實際上,通常隻是中心容器塊發生變化,其餘的通常保持不變。 為此,Jinja2提供了一種在模闆之間進行繼承的好方法。 擁有一個基礎模闆是一個好習慣,我們可以在該模闆中建構網站的基本布局以及頁眉和頁腳。
我将建立一個小應用程式來展示不同類别的産品清單。 對于樣式,我将使用Bootstrap架構對模闆進行基本設計。 現在,應用程式結構如下所示。
flask_app/
my_app.py
templates/
- base.html
- home.html
- product.html
static/
css/
- bootstrap.min.css
- main.css
js/
- bootstrap.min.js
在這裡,可以從上述引導網站下載下傳
static/css/bootstrap.min.css
和
static/js/bootstrap.min.js
。 其餘的應用程式代碼如下所示。
flask_app / my_app.py
from flask import Flask, render_template, abort
app = Flask(__name__)
PRODUCTS = {
'iphone': {
'name': 'iPhone 5S',
'category': 'Phones',
'price': 699,
},
'galaxy': {
'name': 'Samsung Galaxy 5',
'category': 'Phones',
'price': 649,
},
'ipad-air': {
'name': 'iPad Air',
'category': 'Tablets',
'price': 649,
},
'ipad-mini': {
'name': 'iPad Mini',
'category': 'Tablets',
'price': 549
}
}
@app.route('/')
@app.route('/home')
def home():
return render_template('home.html', products=PRODUCTS)
@app.route('/product/<key>')
def product(key):
product = PRODUCTS.get(key)
if not product:
abort(404)
return render_template('product.html', product=product)
在此檔案中,我已對産品清單進行了寫死,以使應用程式更簡單,并且僅關注模闆部分。 我建立了兩個端點
home
和
product
,前者用于列出所有産品,而後者則打開單個頁面。
flask_app / static / css / main.css
body {
padding-top: 50px;
}
.top-pad {
padding: 40px 15px;
text-align: center;
}
該檔案包含一些自定義CSS,我添加了這些自定義CSS可使模闆更清晰易讀。 現在讓我們看一下模闆。
flask_app / templates / base.html
<!DOCTYPE html>
<html >
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Jinja2 Tutorial - Tutsplus</title>
<link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" target="_blank" rel="external nofollow" rel="stylesheet">
<link href="{{ url_for('static', filename='css/main.css') }}" target="_blank" rel="external nofollow" rel="stylesheet">
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="{{ url_for('home')}}" target="_blank" rel="external nofollow" >Tutsplus - Jinja2 Tutorial</a>
</div>
</div>
</div>
<div class="container">
{% block container %}{% endblock %}
</div>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script>
</body>
</html>
請注意使用
url_for()
為靜态檔案和其他連結建立URL。 這是Flask提供的非常友善的工具。 在文檔中閱讀有關此内容的更多資訊。 這裡要注意的另一個重要點是
{% block container %}{% endblock %}
的用法,這是Jinja2的非常關鍵的組成部分,緻力于使模闆子產品化和可繼承。 接下來的幾個檔案将使這一點更加清晰。
flask_app / templates / home.html
{% extends 'base.html' %}
{% block container %}
<div class="top-pad">
{% for id, product in products.iteritems() %}
<div class="well">
<h2>
<a href="{{ url_for('product', key=id) }}" target="_blank" rel="external nofollow" >{{product['name'] }}</a>
<small>$ {{ product['price'] }}</small>
</h2>
</div>
{% endfor %}
</div>
{% endblock %}
了解此模闆如何擴充
base.html
并提供
{% block container %}
。
{% for %}
行為就像普通的for循環一樣,在我們用來建立産品清單的任何語言中。
flask_app / templates / product.html
{% extends 'home.html' %}
{% block container %}
<div class="top-pad">
<h1>{{ product['name'] }}
<small>{{ product['category'] }}</small>
</h1>
<h3>$ {{ product['price'] }}</h3>
</div>
{% endblock %}
上面的模闆實作了單個産品頁面。
現在,通過執行以下指令運作該應用程式。
flask --app=my_app run
正在運作的應用看起來像下面的螢幕截圖所示。 隻需在浏覽器中打開http://127.0.0.1:5000/home 。
單擊任何産品以檢視單個産品頁面。
結論
在本教程中,我們已經看到了如何使用Jinja2在基于Flask的應用程式中布局模闆結構。 我們還看到了如何使用塊來利用模闆中的繼承。
在本系列的下一部分中,我們将看到如何編寫自定義過濾器,自定義上下文處理器和宏。
翻譯自: https://code.tutsplus.com/tutorials/templating-with-jinja2-in-flask-essentials--cms-25571