前言
網站框架有一個美美的前端是非常重要的一件事,畢竟如果你不是單純提供API服務的話,最後呈現的仍是網站前端頁面。然而如何在Flask中渲染你的前端畫面呢?讓我們繼續看下去…
目前 Python Flask 概念與實作 大致規劃為
- 佈置環境
- Flask model運用(一)
- Web server概念(二)
- 專案檔案分佈(三)
- 連接資料庫(四)
- 渲染模板(五)
- 登入功能(六)
- Blog功能(七)
在開發過程中,Test(測試)其實也很重要,但礙於缺乏經驗,若之後有望的話再補上(專案打包、網站優化等等亦同)
Bootstrap
有前端開發經驗的人應該對bootstrap不陌生,bootstrap是一個前端框架,裡面有寫好漂漂亮亮的HTML, CSS, JavaScript模板開放給你使用,而flask也有套件可以連接bootstrap。相關使用教學請參閱使用 Flask Bootstrap 渲染你的HTML
Jinja 2
在使用 Flask Bootstrap 渲染你的HTML中,我們已經知道如何渲染模板,雖然還沒詳述jinja 2,但基本上與python語法差異不大,主要都使用{}將語法包起來,而瀏覽器會將jinja 2語法轉成html。(當然jinja 2還有很多語法e.g. import等等)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| {# 註解: 瀏覽器不會編譯這裡 #}
{% set price = 250 %}
<span>啊嬤說高麗菜一斤{{ price}} {% if price >= 1000 %} 夭壽貴 {% elif price >=50 %} 普通啦 {% else %} 修夠大碗 {% endif %} </span>
<span>啊嬤叫你 {% for i in range(5) %} 緊凳來喔~ {% endfor %} </span>
|
使用Jina 2繼承模板
前端網站通常都有首頁與很多分頁,正常來說我們希望這些頁面都使用同一個主題,因此會設計一個公版模型。如此一來,可以保持每個分頁一至,並且省下很多時間在複製貼上與減少重複的code。
以甜點訂餐網站Shijuu 西啾來說,大致上有這些頁面:
- 首頁
index.html
- 商品頁面
products.html
- 訂單查詢
order_query.html
- 關於shijuu
about.html
可以看得出來是使用同一個模板,而下面的架構除了<main>標籤以外,幾乎每一個都是相同的
結構大致是這樣:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Shijuu</title> </head> <body> <header>navbar</header> <main> </main> <footer>頁尾</footer> </body> </html>
|
Jija 2有模板繼承功能,我們新增base.html,將上述的html寫入,並新增Jija 2語法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <!DOCTYPE html> <html> <head></head> <body> <header>navbar</header> <main> {% block container %} {% end block %} </main> <footer>頁尾</footer> </body> </html>
|
有了base.html,我們的index.html可以直接從<main>標籤開始撰寫!!
1 2 3 4 5 6 7 8 9
| {# 繼承'base.html' #} {% extends "base.html" %}
{# 覆蓋block container #} {% block container %} <section></section> <section></section> {% end block %}
|
如此一來,每一個.html均變得非常簡潔,且再也不用擔心改code牽一髮而動全身。
若base.html越來越臭長,也可以新增navbar.html & footer.html 等,並使用{% include %}標籤。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <!DOCTYPE html> <html> <head></head> <body> <header> {# 引入'navbar.html' #} {% include "navbar.html" %} </header> <main> {% block container %} {% end block %} </main> <footer> {# 引入'footer.html' #} {% include "footer.html" %} </footer> </body> </html>
|
檔案分佈如下所示:
1 2 3 4 5 6 7 8 9 10 11 12
| . ├── run.py └── app ├── __init__.py ├── routes.py ├── models.py ├── forms.py ├── static └── templates ├── base.html ├── about.html └── index.html
|
Flash
Flask提供Flash這個好用的功能,顧名思義一閃即逝,flask會將警示訊息等加入session的message中。且僅Flash只會觸發一次,常用作警示、提示等用途。Flash的Jinja 2語法通常寫在base.html中,如此一來所有模板也能繼承。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
<main> <body> <div class="container"> {% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} {% for category, message in messages %} <div class="alert alert-{{ category }} alert-dismissible fade show" role="alert"> <span class="alert-inner--text">{{ message }}</span> <button type="button" class="close" data-dismiss="alert" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> {% endfor %} {% endif %} {% endwith %} </div>
{% block container%} {% end block %} </body> </main>
|
1 2 3 4 5 6 7 8 9 10
|
@app.route('/') def index() if "username" in session: flash(f"Logged in as {session['username']}", category="success") return render_template("index.html")
|
結論