Flask模板引擎——Jinja2
模板是一個包含響應文字的檔案,其中包含用佔位變量表示的動態部分,其具體指只在請求的上下文中才能知道。使用真是隻替換變數,再返回最終得到的響應字串,這一過程稱為渲染。為了渲染模板,Flask使用了一個名為Jinja2的強大模板引擎。
1. 渲染模板
預設情況下,Flask在程式資料夾中的templates子資料夾中尋找模板。
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html' )
@app.route('/user/<name>')
def user(name):
return render_template('user.html', name=name)
render_template 函式的第一個引數是模板的檔名(index.html,user.html),隨後的引數都是鍵值對(name=name),表示模板中變數的真實值。
2. 變數
template/user.html:Jinja2模板
<h1>Hello,{{ name }}!<h1>
{{ name }}結構表示一個變數,告訴模板引擎這個位置的值從渲染模板時使用的資料中獲取。
可以使用過濾器修改變數,過濾器名稱新增在變數名之後,中間使用豎線分割。
Hello,{{ name|capitalize }}
Jinja2變數過濾器:
safe: 渲染時不轉義
capitalize:把值的首字母轉換成大寫,其他字母轉換成小寫
lower: 把值轉換成小寫形式
upper: 把值轉換成大寫形式
title: 把值中每個單詞的首字母都轉換成大寫
trim: 把值的首尾空格都去掉
striptags: 渲染之前把值中所有的HTML標籤都刪掉
3.控制結構
if迴圈
例:
{%if user %}
Hello, {{ user }} !
{% else %}
Hello, Stranger!
{% endif %}
for迴圈
<ul>
{% for comment in comments %}
<li>{{ comment }}<li>
{% endfor %}
</ul>
巨集
巨集類似於函式。需要在多處重複使用的模板程式碼片段可以寫入單獨的檔案,再包含在所有模板中,以避免重複。另一種重複使用程式碼的強大方式是模板繼承。
例:
首先建立一個名為base.html的基模板。
<html>
<head>
{% block head %}
<title>{% block title %}{% endblock %} - My Application</titel>
{% endblock %}
</head>
<body>
{% block body %}{% endblock %}
</body>
<html>
由block標籤定義的元素可以在衍生模板中修改。head,title,body,注意title包含在head中
下面示例是基模板的衍生模板。
{% extends "base.html" %}{% block title %}index{% endblock %}{% block head %}{{ super }}
<style></style>
{% endblock %}{% block body %}
<h1>Hello, World!</h1>
{% endblock %}
extends指令宣告這個模板衍生自base.html。基模板中的三個塊被重新定義,模板引擎會將其插入適當的位置。**注意新定義的head塊,在基模板中其內容不是空的,所以使用super()獲取原來的內容。
4.自定義錯誤頁面
最常見的錯誤程式碼有兩個:404,客戶端請求未知頁面或路由時顯示;500,有未處理的異常時顯示。
示例:自定義錯誤頁面
@app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'), 404
@app.errorhandler(500)
def internal_server_error(e):
return render_template('500.html'), 500
錯誤處理程式中引用的模板也需要編寫。這些模板應該和常規頁面使用相同的佈局,因此要有一個導航條和顯示錯誤訊息的頁面頭部。
Flask-Bootstrap提供了一個具有頁面基本佈局的基模板。
示例:
{% extends "bootstrap/base.html" %}{% block title %}Flasky{% endblock %}{% block navbar %}
<div class="navbar navbar-inverse" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<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="/">Flasky</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/">Home</a></li>
</ul>
</div>
</div>
</div>
{% endblock %}{% block content %}
<div class="container">
{% block page_content %}{% endblock %}
</div>
{% endblock %}
這是一個繼承自bootstrap/base.html的新模板,其中定義了導航條。content塊中只有個div容器,其中包含了一個名為page_content的新的空塊,塊中的內容由衍生模板定義。
通過繼承base.html模板寫404.html。示例:
{% extends "base.html" %}{% block title %}Flasky - Page Not Found{% endblock %}{% block page_content %}
<div class="page-header">
<h1>Not Found</h1>
</div>
{% endblock %}
505.html:
{% extends "base.html" %}{% block title %}Flasky - Internal Server Error{% endblock %}{% block page_content %}
<div class="page-header">
<h1>Internal Server Error</h1>
</div>
{% endblock %}
user.html:
{% extends "base.html" %}{% block title %}Flasky{% endblock %}{% block page_content %}
<div class="page-header">
<h1>Hello, {{ name }}!</h1>
</div>
{% endblock %}
5.連結
Flask提供了url_for()輔助函式,它可以使用程式URL對映中儲存的資訊生成URL。
使用url_for()生成動態地址時,將動態部分作為關鍵字引數傳入。例如:url_for(‘user’, name = ‘john’, _external = True)的返回結果時http://localhost:5000/user/john.
傳入url_for()的關鍵字引數不僅限於動態路由中的引數。函式能將任何額為引數新增到查詢字元中。
6.靜態檔案
預設設定下,Flask在程式根目錄中名為static的子目錄中尋找靜態檔案。
示例展示瞭如何在程式的基模板中放置favicon.ico圖示(此圖示就是Flask的logo)。這個圖示會顯示在瀏覽器的位址列中。
示例:
...
{% block head %}
{{ super() }}
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon">
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon">
{% endblock %}
...
圖示的宣告會插入head塊的末尾。使用super()保留基模板中定義的塊的原始內容。
7.使用Flask-Moment本地化日期和時間
Flask-Moments時一個Flask擴充套件,用於把moment.js整合到jinjia2模板中。
引入moment.js庫(在base.html模板底部):
...
{% block scripts %}
{{ super() }}
{{ moment.include_moment() }}
{% endblock %}
在hello.py中加入一個datetime變數:
...
from datetime import datetime
...
moment = Moment(app)
...
@app.route('/')
def index():
return render_template('index.html',
current_time=datetime.utcnow())
使用Flask-Moment渲染時間戳(在index.html中加入):
...
<p>The local date and time is {{ moment(current_time).format('LLL') }}.</p>
<p>That was {{ moment(current_time).fromNow(refresh=True) }}.</p>