《Flask 入門教程》第 3 章:模板

greylihui發表於2018-12-16

在一般的 Web 程式裡,訪問一個地址通常會返回一個包含各類資訊的 HTML 頁面。因為我們的程式是動態的,頁面中的某些資訊需要根據不同的情況來進行調整,比如對登入和未登入使用者顯示不同的資訊,所以頁面需要在使用者訪問時根據程式邏輯動態生成。

我們把包含變數和運算邏輯的 HTML 或其他格式的文字叫做模板,執行這些變數替換和邏輯計算工作的過程被稱為渲染,這個工作由我們這一章要學習使用的模板渲染引擎——Jinja2 來完成。

按照預設的設定,Flask 會從程式例項所在模組同級目錄的 templates 資料夾中尋找模板,我們的程式目前儲存在專案根目錄的 app.py 檔案裡,所以我們要在專案根目錄建立這個資料夾:

$ mkdir templates複製程式碼

模板基本語法

在社交網站上,每個人都有一個主頁,藉助 Jinja2 就可以寫出一個通用的模板:

<h1>{{ username }}的個人主頁</h1>
{% if bio %}
    <p>{{ bio }}</p>  {# 這裡的縮排只是為了可讀性,不是必須的 #}
{% else %}
    <p>自我介紹為空。</p>
{% endif %}  {# 大部分 Jinja 語句都需要宣告關閉 #}複製程式碼

Jinja2 的語法和 Python 大致相同,你在後面會陸續接觸到一些常見的用法。在模板裡,你需要新增特定的定界符將 Jinja2 語句和變數標記出來,下面是三種常用的定界符:

  • {{ ... }} 用來標記變數。
  • {% ... %} 用來標記語句,比如 if 語句,for 語句等。
  • {# ... #} 用來寫註釋。

模板中使用的變數需要在渲染的時候傳遞進去,具體我們後面會了解。

編寫主頁模板

我們先在 templates 目錄下建立一個 index.html 檔案,作為主頁模板。主頁需要顯示電影條目列表和個人資訊,程式碼如下所示:

templates/index.html:主頁模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>{{ name }}'s Watchlist</title>
</head>
<body>
    <h2>{{ name }}'s Watchlist</h2>
    {# 使用 length 過濾器獲取 movies 變數的長度 #}
    <p>{{ movies|length }} Titles</p>
    <ul>
        {% for movie in movies %}  {# 迭代 movies 變數 #}
        <li>{{ movie.title }} - {{ movie.year }}</li>  {# 等同於 movie['title'] #}
        {% endfor %}  {# 使用 endfor 標籤結束 for 語句 #}
    </ul>
    <footer>
        <small>&copy; 2018 <a href="http://helloflask.com/tutorial">HelloFlask</a></small>
	</footer>
</body>
</html>複製程式碼

為了方便對變數進行處理,Jinja2 提供了一些過濾器,語法形式如下:

{{ 變數|過濾器 }}複製程式碼

左側是變數,右側是過濾器名。比如,上面的模板裡使用 length 過濾器來獲取 movies 的長度,類似 Python 裡的 len() 函式。

提示 訪問 http://jinja.pocoo.org/docs/2.10/templates/#list-of-builtin-filters 檢視所有可用的過濾器。

準備虛擬資料

為了模擬頁面渲染,我們需要先建立一些虛擬資料,用來填充頁面內容:

app.py:定義虛擬資料

name = 'Grey Li'
movies = [
    {'title': 'My Neighbor Totoro', 'year': '1988'},
    {'title': 'Dead Poets Society', 'year': '1989'},
    {'title': 'A Perfect World', 'year': '1993'},
    {'title': 'Leon', 'year': '1994'},
    {'title': 'Mahjong', 'year': '1996'},
    {'title': 'Swallowtail Butterfly', 'year': '1996'},
    {'title': 'King of Comedy', 'year': '1999'},
    {'title': 'Devils on the Doorstep', 'year': '1999'},
    {'title': 'WALL-E', 'year': '2008'},
    {'title': 'The Pork of Music', 'year': '2012'},
]複製程式碼

渲染主頁模板

使用 render_template() 函式可以把模板渲染出來,必須傳入的引數為模板檔名(相對於 templates 根目錄的檔案路徑),這裡即 'index.html'。為了讓模板正確渲染,我們還要把模板內部使用的變數通過關鍵字引數傳入這個函式,如下所示:

app.py:返回渲染好的模板作為響應

from flask import Flask, render_template

# ...

@app.route('/')
def index():
    return render_template('index.html', name=name, movies=movies)複製程式碼

為了更好的表示這個檢視函式的作用,我們把原來的函式名 hello 改為 index,意思是“索引”,即主頁。

在傳入 render_template() 函式的關鍵字引數中,左邊的 movies 是模板中使用的變數名稱,右邊的 movies 則是該變數指向的實際物件。這裡傳入模板的 name 是字串,movies 是列表,但能夠在模板裡使用的不只這兩種 Python 資料結構,你也可以傳入元組、字典、函式等。

render_template() 函式在呼叫時會識別並執行 index.html 裡所有的 Jinja2 語句,返回渲染好的模板內容。在返回的頁面中,變數會被替換為實際的值(包括定界符),語句(及定界符)則會在執行後被移除(註釋也會一併移除)。

現在訪問 http://localhost:5000/ 看到的程式主頁如下圖所示:


《Flask 入門教程》第 3 章:模板


本章小結

這一章我們編寫了一個簡單的主頁。結束前,讓我們提交程式碼:

$ git add .
$ git commit -m "Add index page"
$ git push複製程式碼

提示 你可以在 GitHub 上檢視本書示例程式的對應 commit:17b579d

進階提示

  • 使用 Faker 可以實現自動生成虛擬資料,它支援豐富的資料型別,比如時間、人名、地名、隨機字元等等……
  • 除了過濾器,Jinja2 還在模板中提供了一些測試器、全域性函式可以使用;除此之外,還有更豐富的控制結構支援,有一些我們會在後面學習到,更多的內容則可以訪問 Jinja2 文件學習。
  • 如果你是《Flask Web 開發實戰》的讀者,模板相關內容可以在第 3 章《模板》找到,Faker 相關內容可以在第 7 章找到。

相關文章