模板是一個包含響應文本的文件,其中包含用佔位變量表示的動態部分。使用真實值替換變量,再返回最終得到的響應字符串,叫渲染。爲了渲染模板,Flask使用Jinja2的模板引擎。
3.1 Jinja2模板引擎
最簡單的Jinja2模板是一個包含響應文本的文件
index.html
<h1>Hello World!</h1>
user.html
<h1>Hello,{{ name }}!</h1>
3.1.1 渲染模板
Flask默認在程序文件夾中的templates子文件夾中找模板。
C:\Windows\System32\flasky\templates
hello.py
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)
Flask提供的render_template函數第一個參數爲模板的文件名,第二個參數爲鍵值對(模板中變量對應的真實值)
3.1.2 變量
{{ name }}結構表示一個變量,是一種特殊的佔位符。Jinja2支持所有類型的變量。
<p>A value from a dictionary:{{ mydict[‘key’] }}.</p>
<p>A value from a list:{{ mylist[‘3’] }}.</p>
<p>A value from an object’s method:{{ myobj.somemethod() }}.</p>
可以使用過濾器修改變量,過濾器名添加在變量名後,中間豎線分隔
Hello,{{ name|capitalize }}
以首字母大寫形式顯示變量name的值
常用過濾器
safe:渲染值時不轉義,注意:不可在不可信的值上使用safe過濾器
capitalize:值的首字母轉換成大寫,其他小寫
lower:值轉換成小寫
upper:值轉換成大寫
title:值中每個單詞的首字母轉換成大寫
trim:把值的首尾空格去掉
striptags:渲染之前把值中所有的HTML標籤刪掉
3.1.3 控制結構
3.1.3.1 條件控制語句
{% if user %}
Hello,{{ user }}!
{% else %}
Hello,Stranger!
{% endif %}
3.1.3.2 for循環
<ul>
{% for comment in comments %}
<li>{{ comment }}</li>
{% endfor %}
</ul>
3.1.3.3 宏
{% macro render_comment(comment) %}
<li>{{ comment }}</li>
{% end macro %}
<ul>
{% for comment in comments %}
{{ render_comment(comment) }}
{% endfor %}}
</ul>
爲了重複使用宏,可單獨保存在文件中,使用時在模板中導入
{% import ‘macro.html’ as macros %}
<ul>
{% for comment in comments %}
{{ macros.render_comment(comment) }}
{% endfor %}
</ul>
3.1.3.4 重複使用的模板代碼片段
寫入單獨的文件,再包含再所有模板中
{% include ‘common.html’ %}
3.1.3.5 模板繼承
基模板
base.html
<html>
<head>
{% block head %}
<title>{% block title %}{% endblock %} - My Application</title>
{% endblock %}
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>
基模板的衍生模板
{% extends “base.html” %}
{% block title %}Index{% endblock %} //title包含在head所以要先聲明
{% block head %}
{{ super() }}
<style>
</style>
{% endblock %}
{% block body %}
<h1>Hello,World!</h1>
{% endblock %}
extends指令聲明模板衍生自base.html。基模板的3個塊被重新定義,其中head塊的內容使用super()獲取原來的內容。
3.2 使用Flask-Bootstrap集成Twitter Bootstrap
Bootstrap是Twitter開發的一個開源客戶端框架,不涉及服務器。服務器需要提供引用了Bootstrap層疊樣式表(CSS)和JavaScript文件的HTML響應。
我們使用Flask-Bootstrap的Flask擴展集成Bootstrap
pip stall flask-bootstrap
3.2.1 Flask擴展的初始化
from flask_bootstrap import Bootstrap
bootstrap = Bootstrap(app)
templates/user.html
{% 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">
<div class="page-header">
<h1>Hello, {{ name }}!</h1>
</div>
</div>
{% endblock %}
3.3 自定義錯誤頁面
Flask允許程序使用給予模板的自定義錯誤頁面。常見錯誤代碼: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
1.templates/user.html
{% extends "base.html" %}
{% block title %}Flasky{% endblock %}
{% block page_content %}
<div class="page-header">
<h1>Hello, {{ name }}!</h1>
</div>
{% endblock %}
2. .templates/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 %}
3.4 鏈接
具有多個路由的程序都需要鏈接來連接不同頁面。直接編寫簡單路由的URL鏈接,在包含可變部分的動態路由會很困難,而且對路由產生不必要的依賴關係。
Flask提供了url_for()輔助函數,可以使用程序URL映射中保存的信息生成URL。
url_for()函數最簡單的用法是以視圖函數名作爲參數,返回URL。例如:url_for(‘index’)得到的結果/;url_for(‘index’,_external=True)返回絕對地址,http://localhost:5000/。
url_for()生成動態地址時,將動態部分作爲關鍵字參數傳入。url_for(‘user’,name=’john’,_external=True)返回http://localhost:5000/user/john。還可以將額外參數添加到查詢字符串,url_for(‘user’,page=2)返回/?page=2
3.5 靜態文件
Flask默認到程序根目錄中名爲static的子目錄中尋找靜態文件
在基模板中放置favicon.ico圖標
{% 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 %}
3.6 Flask-Moment本地化日期和時間
安裝pip install flask-moment
1.hello.py
from datetime import datetime
from flask_moment import Moment
moment = Moment(app)
@app.route('/')
def index():
return render_template('index.html', current_time=datetime.utcnow())
2.templates/base.html
{% block scripts %}
{{ super() }}
{{ moment.include_moment() }}
{% endblock %}
3.templates/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>