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