作者 | ipython
2、集成Twitter Bootstrap的Flask-Bootstrap
Bootstrap是Twitter的一個(gè)開(kāi)源框架,提供用戶交互組件來(lái)創(chuàng)建一個(gè)清新且有吸引力的web頁(yè)面,并兼容所有現(xiàn)代web瀏覽器。
Bootstrap是一個(gè)客戶端框架,服務(wù)端不直接參與。服務(wù)端需要做的就是提供HTML響應(yīng),引用層疊樣式表(CSS)和JavaScript文件并通過(guò)HTML、CSS、和JavaScript代碼來(lái)實(shí)例化需要的組件。模板是做這些的理想地方。
集成Bootstrap到應(yīng)用程序最好的方式是在模板中做一些必要的改變。一個(gè)簡(jiǎn)單點(diǎn)的途徑就是使用Flask-Bootstrap擴(kuò)展去簡(jiǎn)化集成工作。可以通過(guò)pip來(lái)安裝Flask-Bootstrap:
(venv) $ pip install flask-bootstrap
Flask擴(kuò)展通常在應(yīng)用程序?qū)嵗粍?chuàng)建的時(shí)候初始化。示例3-4展示Flask-Bootstrap的初始化。
示例3-4. hello.py:Flask-Bootstrap初始化
from flask.ext.bootstrap import Bootstrap
# ...
bootstrap = Bootstrap(app)
和第二章的Flask-Script一樣,F(xiàn)lask-Bootstrap從flask.ext命名空間導(dǎo)入并通過(guò)傳遞應(yīng)用程序?qū)嵗綐?gòu)造函數(shù)來(lái)初始化。
一旦Flask-Bootstrap被初始化,一個(gè)包含所有Bootstrap文件的基礎(chǔ)模板就可供應(yīng)用程序使用了。這個(gè)模板利用Jinja2的模板繼承,應(yīng)用程序則可以擴(kuò)展一個(gè)擁有通用頁(yè)面結(jié)構(gòu),且包含Bootstrap導(dǎo)入的元素的基礎(chǔ)模板。示例3-5展示作為派生模板的新版user.html。
_示例3-5. templates/user.html: 使用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">
<div class="page-header">
<h1>Hello, {{ name }}!</h1>
</div>
</div>
{% endblock %}
Jinja2的extends指令通過(guò)從Flask-Bootstrap引用bootstrap/base.html來(lái)實(shí)現(xiàn)模板的繼承。Flask-Bootstrap的基礎(chǔ)模板提供一個(gè)包含Bootstrap CSS和JavaScript文件的web頁(yè)面骨架。
基礎(chǔ)模板定義了一些可以被派生模板重寫(xiě)的block。block和endblock指令定義了被添加到基礎(chǔ)模板中block的內(nèi)容。
上面的user.html模板定義了三個(gè)block,分別命名為title、navbar和content。基礎(chǔ)模板里的這些block輸出派生模板定義的內(nèi)容。title塊比較簡(jiǎn)單;它的內(nèi)容將出現(xiàn)在<title>標(biāo)簽內(nèi),然后被渲染在HTML文檔的頭部 。navbar和content塊則是為頁(yè)面保留的導(dǎo)航欄和主內(nèi)容。
在這個(gè)模板中,navbar塊使用Bootstrap組件定義了一個(gè)簡(jiǎn)單的導(dǎo)航欄。content塊有個(gè)名為container的<div>,里面嵌套了名為page-header的<div>。圖3-1展示這些操作后應(yīng)用程序長(zhǎng)成啥樣了。
建議:如果你有克隆在GitHub上的應(yīng)用程序,你現(xiàn)在可以運(yùn)行g(shù)it checkout 3b來(lái)切換到這個(gè)版本的應(yīng)用程序。Bootstrap官方文檔 是一個(gè)非常強(qiáng)大的學(xué)習(xí)資料,完全可以復(fù)制粘貼使用那些示例。
圖片3-1. Twitter Bootstrap模板
Flask-Bootstrap的base.html模板定義了一些其他可供派生模板使用的block。表格3-2展示了完整的可用block列表。
表格3-2. Flask-Bootstrap基礎(chǔ)模板中的block
表格3-2中的許多塊用于Flask-Bootstrap自身,所以直接重寫(xiě)它們會(huì)引發(fā)問(wèn)題。例如,styles和scripts塊是Bootstrap定義文件的地方。如果應(yīng)用程序需要新增自己的內(nèi)容到已經(jīng)有一些內(nèi)容的塊中,則必須使用Jinja2的super()。例如,如何在派生模板中寫(xiě)scripts塊,來(lái)給文檔增加新的JavaScript文件:
{% block scripts %}
{{ super() }}
<script type="text/javascript" src="my-script.js"></script>
{% endblock %}
3、自定義錯(cuò)誤頁(yè)面
當(dāng)你輸入錯(cuò)誤路徑在你的瀏覽器地址欄,你會(huì)得到404錯(cuò)誤代碼頁(yè)面。目前的錯(cuò)誤頁(yè)面很普通也沒(méi)有吸引力,且沒(méi)有一致的使用Bootstrap頁(yè)面。
Flask允許應(yīng)用程序自定義基于模板的錯(cuò)誤頁(yè)面,就像常規(guī)的路由。兩個(gè)最常見(jiàn)的錯(cuò)誤代碼,404是在客戶端請(qǐng)求的頁(yè)面或路徑不存在的時(shí)候觸發(fā);500是當(dāng)存在未處理的異常時(shí)觸發(fā)。示例3-6展示如何為這兩個(gè)錯(cuò)誤提供自定義處理。
示例3-6. hello.py:自定義錯(cuò)誤頁(yè)面
@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
錯(cuò)誤處理返回響應(yīng),和視圖函數(shù)一樣。同時(shí)返回相應(yīng)錯(cuò)誤的數(shù)字狀態(tài)碼。
在錯(cuò)誤處理中引用的模板需要自己去寫(xiě)。這些模板需要和常規(guī)的頁(yè)面一樣的布局,所以在這個(gè)示例中需要導(dǎo)航欄和頁(yè)面頭部顯示錯(cuò)誤信息。
編寫(xiě)這些模板的簡(jiǎn)單方式是復(fù)制templates/user.html到templates/404.html和templates/500.html,然后改變這兩個(gè)新文件的頁(yè)面頭部元素來(lái)給出相應(yīng)的錯(cuò)誤信息,但這會(huì)產(chǎn)生很多副本。
Jinja2的模板繼承可以幫助我們解決這個(gè)問(wèn)題。Flask-Bootstrap提供了一個(gè)帶有基本布局頁(yè)面的基礎(chǔ)模板,應(yīng)用程序可以定義自己的、帶有完整頁(yè)面布局的基礎(chǔ)模板,包括導(dǎo)航欄和定義在派生模板中的頁(yè)面內(nèi)容。示例3-7展示了templates/base.html,它是一個(gè)繼承自bootstrap/base.html的新模板且定義了導(dǎo)航欄,但對(duì)于其他模板則是一個(gè)基礎(chǔ)模板,例如templates/user.html、templates/404.html和templates/500.html。
_示例3-7. templates/base.html:帶有導(dǎo)航欄的基礎(chǔ)應(yīng)用程序模板
{% 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 %}
這個(gè)模板中的content塊中只是一個(gè)名為container的<div>元素,它包含了在派生模板中定義的名為page_content的空block。
應(yīng)用程序的模板將從該模板繼承而不是直接從Flask-Bootstrap繼承。示例3-8展示了從templates/base.html繼承來(lái)構(gòu)造一個(gè)自定義404錯(cuò)誤頁(yè)面是如此的簡(jiǎn)單。
示例3-8. templates/404.html:使用模板繼承自定義404錯(cuò)誤頁(yè)面
{% extends "base.html" %}
{% block title %}Flasky - Page Not Found{% endblock %}
{% block page_content %}
<div class="page-header">
<h1>Not Found</h1>
</div>
{% endblock %}
圖片3-2展示在瀏覽器中錯(cuò)誤頁(yè)面是怎樣的。
圖片3-2. 自定義404錯(cuò)誤頁(yè)面
現(xiàn)在templates/user.html模板可以通過(guò)繼承基礎(chǔ)模板來(lái)簡(jiǎn)化它,就像示例3-9展示的這樣。
示例3-9. templates/user.html:使用模板繼承簡(jiǎn)化頁(yè)面模板
{% extends "base.html" %}
{% block title %}Flasky{% endblock %}
{% block page_content %}
<div class="page-header">
<h1>Hello, {{ name }}!</h1>
</div>
{% endblock %}
建議:如果你有克隆在GitHub上的應(yīng)用程序,你現(xiàn)在可以運(yùn)行g(shù)it checkout 3c來(lái)切換到這個(gè)版本的應(yīng)用程序。
原文轉(zhuǎn)載:https://segmentfault.com/a/1190000000755204