範本¶
您已經為您的應用程式撰寫了身份驗證視圖,但是如果您正在執行伺服器並嘗試前往任何 URL,您將會看到 TemplateNotFound
錯誤。那是因為視圖正在呼叫 render_template()
,但是您尚未撰寫範本。範本檔案將會儲存在 templates
目錄中,該目錄位於 flaskr
套件內。
範本是包含靜態資料以及動態資料預留位置的檔案。範本會使用特定資料進行呈現,以產生最終文件。Flask 使用 Jinja 範本庫來呈現範本。
在您的應用程式中,您將使用範本來呈現 HTML,這將顯示在使用者的瀏覽器中。在 Flask 中,Jinja 被配置為對在 HTML 範本中呈現的任何資料進行自動跳脫。這表示呈現使用者輸入是安全的;他們輸入的任何可能搞亂 HTML 的字元,例如 <
和 >
,都將會使用安全值進行跳脫,這些安全值在瀏覽器中看起來相同,但不會造成不必要的影響。
Jinja 的外觀和行為大多與 Python 相似。特殊的定界符用於區分 Jinja 語法與範本中的靜態資料。在 {{
和 }}
之間的任何內容都是將輸出到最終文件的表達式。{%
和 %}
表示控制流程語句,例如 if
和 for
。與 Python 不同,區塊由開始和結束標籤而不是縮排表示,因為區塊內的靜態文字可能會更改縮排。
基礎佈局¶
應用程式中的每個頁面都將在不同的主體周圍具有相同的基本佈局。每個範本將擴展基礎範本並覆寫特定區段,而不是在每個範本中編寫完整的 HTML 結構。
flaskr/templates/base.html
¶<!doctype html>
<title>{% block title %}{% endblock %} - Flaskr</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<nav>
<h1>Flaskr</h1>
<ul>
{% if g.user %}
<li><span>{{ g.user['username'] }}</span>
<li><a href="{{ url_for('auth.logout') }}">Log Out</a>
{% else %}
<li><a href="{{ url_for('auth.register') }}">Register</a>
<li><a href="{{ url_for('auth.login') }}">Log In</a>
{% endif %}
</ul>
</nav>
<section class="content">
<header>
{% block header %}{% endblock %}
</header>
{% for message in get_flashed_messages() %}
<div class="flash">{{ message }}</div>
{% endfor %}
{% block content %}{% endblock %}
</section>
g
在範本中自動可用。根據是否設定了 g.user
(來自 load_logged_in_user
),將顯示使用者名稱和登出連結,或顯示註冊和登入的連結。url_for()
也會自動可用,並用於產生視圖的 URL,而不是手動寫出它們。
在頁面標題之後和內容之前,範本會迴圈遍歷 get_flashed_messages()
傳回的每則訊息。您在視圖中使用 flash()
來顯示錯誤訊息,而這段程式碼將會顯示它們。
這裡定義了三個區塊,這些區塊將在其他範本中被覆寫
{% block title %}
將會變更顯示在瀏覽器標籤頁和視窗標題中的標題。{% block header %}
類似於title
,但會變更顯示在頁面上的標題。{% block content %}
是每個頁面的內容所在的位置,例如登入表單或部落格文章。
基礎範本直接位於 templates
目錄中。為了保持其他範本的組織性,藍圖的範本將放置在與藍圖同名的目錄中。
註冊¶
flaskr/templates/auth/register.html
¶{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}Register{% endblock %}</h1>
{% endblock %}
{% block content %}
<form method="post">
<label for="username">Username</label>
<input name="username" id="username" required>
<label for="password">Password</label>
<input type="password" name="password" id="password" required>
<input type="submit" value="Register">
</form>
{% endblock %}
{% extends 'base.html' %}
告訴 Jinja 這個範本應該取代基礎範本中的區塊。所有呈現的內容都必須出現在 {% block %}
標籤內,這些標籤會覆寫基礎範本中的區塊。
這裡使用的一個有用的模式是將 {% block title %}
放置在 {% block header %}
內。這將設定標題區塊,然後將其值輸出到標頭區塊中,以便視窗和頁面共享相同的標題,而無需寫兩次。
input
標籤在這裡使用 required
屬性。這告訴瀏覽器在填寫完這些欄位之前不要提交表單。如果使用者使用的是不支援該屬性的舊瀏覽器,或者他們使用的是瀏覽器以外的其他東西來發出請求,您仍然希望在 Flask 視圖中驗證資料。即使用戶端也進行了一些驗證,但在伺服器上始終完全驗證資料非常重要。
登入¶
除了標題和提交按鈕之外,這與註冊範本完全相同。
flaskr/templates/auth/login.html
¶{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}Log In{% endblock %}</h1>
{% endblock %}
{% block content %}
<form method="post">
<label for="username">Username</label>
<input name="username" id="username" required>
<label for="password">Password</label>
<input type="password" name="password" id="password" required>
<input type="submit" value="Log In">
</form>
{% endblock %}
註冊使用者¶
現在身份驗證範本已撰寫完成,您可以註冊使用者。請確保伺服器仍在執行中(如果沒有,請執行 flask run
),然後前往 http://127.0.0.1:5000/auth/register。
嘗試在未填寫表單的情況下點擊「註冊」按鈕,並查看瀏覽器是否顯示錯誤訊息。嘗試從 register.html
範本中移除 required
屬性,然後再次點擊「註冊」。頁面將重新載入,並且會顯示視圖中 flash()
產生的錯誤,而不是瀏覽器顯示錯誤。
填寫使用者名稱和密碼,您將被重新導向到登入頁面。嘗試輸入不正確的使用者名稱,或正確的使用者名稱和不正確的密碼。如果您登入,您將會收到錯誤,因為還沒有 index
視圖可以重新導向。
繼續前往 靜態檔案。