我們來看看 The Flask Mega-Tutoral Part II: Templates 說了什麼。Template 是套版的意思,那套版是什麼呢?我們慢慢看下去。
這個教學系列最後會完成一個微博網站。作者命名他為 microblog ,也就是微博的意思。
開始之前請確定已經有 Part I 練習的完成品。執行 flask/Scripts/python run.py 後,可以從瀏覽器打開 http://localhost:500 看到到 Hello, World! 的字樣。
要解決的問題
我們讓這小程式熱鬧、好看一點。所以畫面上加的大標題,然後跟使用者打個招呼。但是目前為止還沒有登入的機制,所以使用者就先直接寫死 Minguel (原文作者的名),當然因為只是臨時寫死的東西,所以這使用者要叫什麼都可以。因為要加大標題就要動到畫面的排版,所以只是回傳沒有格式的文字不夠用了,我們把 app/views.py 內容改成 HTML 。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | from app import app
@app.route('/')
@app.route('/index')
def index():
user = { 'nickname': 'Miguel' } # fake user
return '''
<html>
<head>
<title>Home Page</title>
</head>
<body>
<h1>Hello, ''' + user['nickname'] + '''</h1>
</body>
</html>
'''
|
程式中的 user 變數是以大括號建立的 dictionary 物件,因為沒有登入的機制,給的資料只是隨便的假資料,也就是所謂的假物件( mock object )。回傳內容用了三個單引號包著可以直接寫出多行的內容建立含有換行資訊的字串。
如果你還沒發現的話,直接把網頁內容寫到程式中回傳是個很糟的做法。
當畫面開始豐富一點時,程式很快的會變得非常複雜。如果每個畫面的程式都是各自回傳寫好的網頁內容,想要修改整個網站排版時就得一個一個程式修改。這種做法在網站越來越大時完全會行不通。
用套版來處理
如果我們把程式的處理邏輯跟網頁呈現方式分開來的話,就會乾淨很多。你還可以去找個網頁設計師幫你寫超棒的網頁畫面,你來負責寫背後的 Python 程式就好。 (依照過往的經驗,網頁設計師寫出來的網頁畫面最好還是重做,不過目前為止應該可以感受到把邏輯跟畫面分開的好處吧!)套版就是可以把這邏輯跟畫面分開的工具。那就來寫第一個套版吧,寫在 app/templates/index.html :
1 2 3 4 5 6 7 8 | <html>
<head>
<title>{{ title }} - microblog</title>
</head>
<body>
<h1>Hello, {{ user.nickname }}!</h1>
</body>
</html>
|
接下來看如何在 app/views.py 中用這個套版,記得要在第一行加 from flask import render_template :
1 2 3 4 5 6 7 8 | from flask import render_template
from app import app
@app.route('/')
@app.route('/index')
def index():
user = { 'nickname': 'Miguel' } # fake user
return render_template('index.html', title='Home', user=user)
|
render_template 可以把指定的套版檔案套入傳入的參數。背後使用 Jinja2 套版引擎。 Jinja2 以同名參數的內容將套版中的 {{ ... }} 取代。
套版中的控制語句
Jinja2 也可以把控制語句用在套版中的 {% ... %} 區塊,我們把 if 加到套版中看看, app/templates/index.html1 2 3 4 5 6 7 8 9 10 11 12 | <html>
<head>
{% if title %}
<title>{{ title }} - microblog</title>
{% else %}
<title>Welcome to microblog</title>
{% endif %}
</head>
<body>
<h1>Hello, {{ user.nickname }}!</h1>
</body>
</html>
|
套版中的迴圈
登入的會員很有可能想看他在追蹤的人的貼文。我們來看看怎麼做。我們還沒有登入的機制,方便起見,我們先在 views.py 做些假會員資料。
1 2 3 4 5 6 7 8 9 10 11 12 13 | def index():
user = { 'nickname': 'Miguel' } # fake user
posts = [ # 假的貼文陣列
{
'author': {'nickname': 'John'},
'body': 'Beautiful day in Portland!'
},
{
'author': {'nickname': 'Susan'},
'body': 'The Avengers movie was so cool!'
}
]
return render_template('index.html', title='Home', user=user, posts=posts)
|
一個 list 中可以放不定數量的貼文,套版要忠實的把每一筆輸出在結果畫面中。如果要限制顯示的貼文數量,那應該要讓 views.py 中的程式決定 list 中要有幾筆貼文。決定顯示幾筆不是套版的工作。
我們在 app/templates/index.html 加一個 for 迴圈輸出貼文:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <html>
<head>
{% if title %}
<title>{{ title }} - microblog</title>
{% else %}
<title>Welcome to microblog</title>
{% endif %}
</head>
<body>
<h1>Hello, {{ user.nickname }}!</h1>
{% for post in posts %}
<div><p>{{ post.author.nickname }} says: <b>{{ post.body }}</b></p></div>
{% endfor %}
</body>
</html>
|
套版繼承
接下來最後的討論項目。這個 microblog 網站的網頁的最上方要有一塊導覽列。裡面會包含編輯個人資訊、登入、登出等連結。我們可以直接把導覽列寫到 index.html 中,不過網站越大時網頁也跟著變多,如果每次要改導覽頁時都要從 index.html 複製過去會很麻煩。萬一複製後又要改導覽列,那就得花很多時間改了。
還有 Jinja2 的套版繼承功能,他可以讓我們把所有套版相同的部分都拉出來放到一個共用的套版中,然後再讓所有的套版繼承這個共用的套版。
我們就來新增這個共用的套版,放在 app/templates/base.html ,把導覽列跟一些之前寫好的套版內容寫在裡面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <html>
<head>
{% if title %}
<title>{{ title }} - microblog</title>
{% else %}
<title>Welcome to microblog</title>
{% endif %}
</head>
<body>
<div>Microblog: <a href="/index">Home</a></div>
<hr>
{% block content %}{% endblock %}
</body>
</html>
|
1 2 3 4 5 6 7 | {% extends "base.html" %}
{% block content %}
<h1>Hi, {{ user.nickname }}!</h1>
{% for post in posts %}
<div><p>{{ post.author.nickname }} says: <b>{{ post.body }}</b></p></div>
{% endfor %}
{% endblock %}
|
套版就講到這了,不要忘了看原文喔。