作者 | ipython
4、鏈接
任何應(yīng)用程序都有多個路由,必然需要包含鏈接來連接不同的頁面,例如導(dǎo)航欄。
在模板中,對于簡單的路由直接寫URLs做鏈接是非?,嵥槁闊┑模o帶有變量部分的動態(tài)路由建立正確的URLs會變得更加復(fù)雜。此外,在代碼中顯式的寫URLs會在路由上造成不必要的依賴。如果路由重組,模板中的鏈接將被打斷而變得無法訪問。
為了避免這些問題,F(xiàn)lask提供url_for()函數(shù),它會根據(jù)存放在應(yīng)用程序中的URL映射信息來生成URLs。
其最簡單的用法,這個函數(shù)傳入視圖函數(shù)名(或通過app.add_url_route()定義的路由endpoint名)作為它的參數(shù),然后返回它的URL。例如,在當(dāng)前版本的hello.py調(diào)用url_for('index')將返回/。調(diào)用url_for('index', _external=True)將返回一個絕對URL,在該示例中為http://localhost:5000/。
注:相對URLs足以滿足生成鏈接來連接應(yīng)用程序不同的路由。絕對URLs只有在鏈接被用于web瀏覽器的外部才是必須的,例如通過郵件發(fā)送鏈接。
可以使用url_for()并傳遞動態(tài)部分作為關(guān)鍵字參數(shù)來生成動態(tài)URLs。例如,url_for('user', name='join', external=True)會返回http://localhost:5000/user/john。
url_for()可以不限參數(shù)的使用動態(tài)路由。函數(shù)會增加擴展參數(shù)給查詢字符串。例如url_for('index', page=2)會返回/?page=2。
5、靜態(tài)文件
Web應(yīng)用程序不僅僅是由Python代碼和模板組成。大部分的應(yīng)用程序會使用靜態(tài)文件,例如從HTML代碼中引用的圖片、JavaScript源文件和CSS。
你可能需要回憶一下,在第二章中檢查hello.py應(yīng)用程序的URL映射時,有一個static入口在里面。這也是為什么引用定義成/static/<filename>的靜態(tài)文件會被當(dāng)作特殊路由來對待。例如,一個url_for('static', filename='css/style.css', _external=True)調(diào)用會返回http://localhost:5000/static/css/styles.css。
在它的默認(rèn)配置中,F(xiàn)lask會在位于應(yīng)用程序根目錄下名為static的子目錄中尋找靜態(tài)文件??梢栽谶@個目錄下的子目錄組織管理文件。當(dāng)服務(wù)器收到來自之前示例的URL,它會產(chǎn)生一個響應(yīng)包含static/css/styles.css的文件內(nèi)容。
示例3-10展示應(yīng)用程序如何在基礎(chǔ)模板中包含favicon.icon圖標(biāo)并讓瀏覽器將其顯示在地址欄。
示例3-10. templates/base.html:favicon定義
{% 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 %}
圖標(biāo)定義被插入在head塊里的最下面。注意super()是如何保留定義在基礎(chǔ)模板中塊的原始內(nèi)容的。
建議:如果你有克隆在GitHub上的應(yīng)用程序,你現(xiàn)在可以運行g(shù)it checkout 3d來切換到這個版本的應(yīng)用程序。
6、Flask-Moment中的本地化日期和時間
當(dāng)用戶工作在世界各個不同的地方,在web應(yīng)用程序中處理日期和時間就變成了一個比較重要的問題。
服務(wù)器使用統(tǒng)一的時間單位,和每個用戶的位置無關(guān),所以使用世界標(biāo)準(zhǔn)時間(UTC)。對于用戶,看到UTC格式的時間肯定會感到困惑,用戶總是希望看到根據(jù)當(dāng)?shù)亓?xí)慣顯示的日期和時間。
一個優(yōu)雅的解決方案是允許服務(wù)器只發(fā)送UTC時間給web瀏覽器,由瀏覽器轉(zhuǎn)為當(dāng)?shù)貢r間并渲染。Web瀏覽器在這個問題上做的更好,因為他們可以訪問用戶電腦的所在的時區(qū)和地區(qū)設(shè)置。
有一個優(yōu)秀的客戶端開源庫moment.js,用JavaScript編寫的,用于在瀏覽器上渲染日期和時間。Flask-Moment是一個集成moment.js到Jinja2模板的Flask擴展??梢酝ㄟ^pip來安裝:
(venv) $ pip install flask-moment
示例3-11展示擴展初始化。
示例3-11. hello.py:初始化Flask-Moment
from flask.ext.moment import Moment
moment = Moment(app)
Flask-Moment除了依賴moment.js外,還依賴jquery.js。這兩個庫需要直接包含在HTML文檔,這種情況下你可以選擇使用什么版本,或通過擴展提供的幫助函數(shù)來引用內(nèi)容分發(fā)網(wǎng)絡(luò)(CDN)的測試版本庫。因為Bootstrap已經(jīng)包含了jquery.js,所以只需要將moment.js增加到這個示例中。示例3-12展示這個庫是如何被加載到基礎(chǔ)模板scripts中的。
示例3-12. templates/base.html:導(dǎo)入moment.js庫
{% block scripts %}
{{ super() }}
{{ moment.include_moment() }}
{% endblock %}
為了可以使用時間戳,F(xiàn)lask-Moment創(chuàng)建moment類給模板使用。示例3-13傳遞current_time變量給模板去渲染。
示例3-13. hello.py:增加datetime變量
from datetime import datetime
@app.route('/')
def index():
return render_template('index.html', current_time=datetime.utcnow())
示例3-14展示如何在模板中渲染current_time。
示例3-14. templates/index.html:使用Flask-Moment渲染時間戳
<p>The local date and time is {{ moment(current_time).format('LLL') }}.</p>
<p>That was {{ moment(current_time).fromNow(refresh=True) }}</p>
format('LLL')根據(jù)客戶端電腦的時區(qū)和地區(qū)設(shè)置來格式化顯示日期和時間。參數(shù)決定了渲染的樣式,從L到LLL對應(yīng)不同的詳細(xì)級別。format()函數(shù)還可以接受自定義的格式說明符。
fromNow()渲染樣式顯示在第二行,渲染一個相對時間戳并隨著時間的推移自動刷新它。最初這個時間戳將顯示為“幾秒鐘前”,但隨著時間的流逝刷新選項將保持更新,所以如果你離開已打開幾分鐘的頁面你會看到文本變?yōu)椤耙环昼娗啊?,然后“兩分鐘前”,等等?/p>
建議:如果你有克隆在GitHub上的應(yīng)用程序,你現(xiàn)在可以運行g(shù)it checkout 3e來切換到這個版本的應(yīng)用程序。
Flask-Moment通過moment.js實現(xiàn)了format(),fromNow(),fromTime(), calendar(),valueOf()和unix()方法。查閱文檔,了解提供的所有格式化選項。
注:Flask-Moment假定時間戳由服務(wù)端應(yīng)用程序中表示成UTC格式的“naive”datetime對象來處理。參閱標(biāo)準(zhǔn)庫datetime包文檔關(guān)于date和time對象的navie和aware信息。
Flask-Moment渲染的時間戳可以本地化成多種語言。在模板中通過傳遞語言代碼到lang()函數(shù)來選擇語言:
{{ moment.lang('es') }}
學(xué)完本章中討論的所有技術(shù),您應(yīng)該能夠為您的應(yīng)用程序構(gòu)建現(xiàn)代、用戶友好的網(wǎng)頁。下一章涉及模板沒有討論的一個方面:如何通過web表單與用戶進行交互。
原文轉(zhuǎn)自:https://segmentfault.com/a/1190000000760163