Flask Mega-Tutorial 中文教程 V2.0 第11章:整容
最近在Flask Web Development作者部落格看到第二版Flask Mega-Tutorial已在2017年底更新,現翻譯給大家參考,希望幫助大家學習flask。
這是Flask Mega-Tutorial系列的第十一章,其中我將告訴您如何使用基於Bootstrap使用者介面框架的新模板替換基本HTML模板。
供您參考,以下是本系列文章的列表。
你把玩Microblog應用程式已經有一段時間了,所以我確定你注意到我沒有花太多時間美化它,或者更具體地說,我沒有花時間在那上面。所有的模板只使用了基礎樣式,絕對沒有自定義樣式。對我來說,專注於應用程式的實際邏輯是很有用的,因為不會分心去編寫好看的HTML和CSS的程式碼。
但是我現在專注於這個應用程式的後端部分已經有一段時間。因此,在本章中我將暫停一下,並將花一些時間向您展示如何使應用程式看起來更加優雅和專業。
本章將與之前的章節略有不同,因為我不會像往常解說Python那樣,事無鉅細,畢竟Python才是本教程的主要內容。建立漂亮的網頁是一個很大的主題,與Python Web後端開發很大程度上無關,但我將討論如何處理前端的一些基本指導和想法,並且您還將通過重新設計外觀來研究和學習它。
CSS框架
雖然我們可以說寫程式碼很難,但與網頁設計師相比,我們的痛苦是無足輕重的,他們必須在所有的網路瀏覽器上編寫具有良好和一致外觀的模板。雖然它近年來這種情況得到一定程度的緩解,但是在某些瀏覽器中仍然存在一些模糊的錯誤或奇怪的設定,這使得設計網頁的任務變得非常困難。如果您還需要相容螢幕限制裝置(如平板電腦和智慧手機)的瀏覽器,這將更加困難。
如果你像我一樣,是一個只想創建出規範網頁的開發人員,但沒有時間或興趣去學習底層機制,並通過編寫原生HTML和CSS來有效實現它,那麼唯一可行的解決方案是使用CSS框架來簡化任務。通過這條方式,您將失去一些創造性的自由,但另一方面,您的網頁在所有瀏覽器中看起來都會很好,而又不需要花費太多精力。CSS框架提供了一組高階CSS類,其中包含用於常見型別的使用者介面元素的預定義樣式。大多數這樣的框架還提供JavaScript元件,以實現不能純粹使用HTML和CSS來完成的功能。
介紹Bootstrap
最受歡迎的CSS框架之一是由Twitter推出的Bootstrap。如果您想看看這個框架可以設計的頁面型別,那麼文件中有一些
以下是使用Bootstrap為您的網頁設定樣式的一些好處:
- 在所有主流Web瀏覽器中都有相似的外觀
- 自適應PC,平板電腦和手機螢幕尺寸
- 可定製的佈局
- 風格精美的導航欄、表單、按鈕,提醒、彈出視窗等。
使用Bootstrap的最直接方法是在基本模板中匯入bootstrap.min.css檔案。您可以下載此檔案的副本並將其新增到專案中,也可以直接從CDN匯入。然後你可以根據文件開始使用它提供的通用CSS類,實在是太棒了。您可能還想匯入包含JavaScript框架程式碼的bootstrap.min.js檔案,以便您也可以使用最高階的功能。
幸運的是,有一個名為Flask-Bootstrap的Flask擴充套件,它提供了一個開箱即用的基本模板,該模板引入了Bootstrap框架。讓我們安裝此擴充套件程式:
(venv) $ pip install flask-bootstrap
使用Flask-Bootstrap
Flask-Bootstrap需要像大多數其他Flask擴充套件一樣進行初始化:
# app/__init__.py: Flask-Bootstrap instance.
# ...
from flask_bootstrap import Bootstrap
app = Flask(__name__)
# ...
bootstrap = Bootstrap(app)
初始化擴充套件後,bootstrap / base.html模板變為可用狀態,並且可以使用
extends
子句從應用程式模板中引用。
但是你記得,我已經使用了extends
子句來繼承我的基礎模板,這允許我將頁面的公共部分放在一個地方。我在base.html模板定義了導航欄,其中包含一些連結,還匯出了一個content
塊。應用程式中的所有其他模板都從基本模板繼承,並向content
塊提供頁面的主要內容。
那麼我如何適配Bootstrap基礎模板呢?其思想是使用一個三級層次結構而不是僅僅使用兩層層次結構。bootstrap/base.html檔案模板提供頁面的基本結構,其中包括Bootstrap框架檔案。這個模板匯出了一些用於派生模板(如title
,navbar
和content
)的塊(請參閱塊的完整列表)。我要更改base.html檔案模板,讓它繼承bootstrap/base.html檔案,並提供title
,navbar
和content
塊。反過來,base.html將為從其派生的模板匯出app_content
塊以定義頁面內容。
下面你可以看看修改base.html後,它是如何從Bootstrap基礎模板繼承。請注意,此列表不包含導航欄的整個HTML,但您可以在GitHub上看到完整的實現,也可以下載本章的程式碼
<!-- app/templates/base.html: Redesigned base template. -->
{% extends 'bootstrap/base.html' %}
{% block title %}
{% if title %}{{ title }} - Microblog{% else %}Welcome to Microblog{% endif %}
{% endblock %}
{% block navbar %}
<nav class="navbar navbar-default">
... navigation bar here (see complete code on GitHub) ...
</nav>
{% endblock %}
{% block content %}
<div class="container">
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<div class="alert alert-info" role="alert">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
{# application content needs to be provided in the app_content block #}
{% block app_content %}{% endblock %}
</div>
{% endblock %}
在這裡,您可以看到我如何從bootstrap/base.html派生此模板,然後分別實現頁面標題,導航欄和頁面內容的三個模板。
title
塊需要使用<title>
標籤來定義用於頁面標題的文字。對於這個塊,我只是移動了原始基本模板中<title>
標籤內的邏輯。
navbar
塊是可選塊,可用於定義導航欄。對於這個塊,我調整了Bootstrap導航欄文件中的示例,以便它在左側展示網站品牌,跟著是Home和Explore連結。然後,我添加了個人主頁和登入/登出連結並使其與頁面右邊框對齊。如上所述,我在上面的示例中省略了HTML,但您可以從本章的下載包中獲取完整的base.html模板。
最後,在content
塊中我定義了一個頂級容器,在其中我有渲染快閃記憶體訊息的邏輯,現在它們將顯示為Bootstrap警報的樣式。接下來是一個新的app_content
塊,它被定義為只有派生模板才能定義自己的內容。
所有頁面模板的原始版本都在名為content
的塊中定義了它們的內容。如上所示,Flask-Bootstrap使用名為content
的塊,因此我將內容塊重新命名為app_content
。所以我的所有模板都必須重新命名才能使用app_content
作為它們的內容塊。例如,這是404.html模板的修改後版本的展示:
<!-- app/templates/404.html: Redesigned 404 error template. -->
{% extends "base.html" %}
{% block app_content %}
<h1>File Not Found</h1>
<p><a href="{{ url_for('index') }}">Back</a></p>
{% endblock %}
渲染Bootstrap表單
Flask-Bootstrap的一個很棒的工作就是渲染表格。Flask-Bootstrap不是必須逐個設定表單欄位的樣式,而是使用一個接受Flask-WTF表單物件作為引數的巨集,並使用Bootstrap樣式渲染出完整的表單。
您可以在下面看到重新設計的register.html模板:
<!-- app/templates/register.html: User registration template. -->
{% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
<h1>Register</h1>
<div class="row">
<div class="col-md-4">
{{ wtf.quick_form(form) }}
</div>
</div>
{% endblock %}
是不是很棒?頂部附近的import
宣告與Python匯入類似。這增加了一個wtf.quick_form()
巨集,在一行程式碼中渲染了完整的表單,包括顯示驗證錯誤的支援,並且適配Bootstrap框架的所有樣式。
再一次,我不會向您展示我為應用程式中的其他表單所做的所有更改,但這些更改都是在您可以在GitHub上下載或檢查到的。
渲染部落格帖子
渲染單個部落格帖子的邏輯被提取到名為_post.html的子模板。我需要對此模板進行一些小的調整,以便在Bootstrap下看起來很好。
<!-- app/templates/_post.html: Redesigned post sub-template. -->
<table class="table table-hover">
<tr>
<td width="70px">
<a href="{{ url_for('user', username=post.author.username) }}">
<img src="{{ post.author.avatar(70) }}" />
</a>
</td>
<td>
<a href="{{ url_for('user', username=post.author.username) }}">
{{ post.author.username }}
</a>
says:
<br>
{{ post.body }}
</td>
</tr>
</table>
渲染分頁連結
分頁連結是Bootstrap提供直接支援的另一個領域。為此,我再一次檢視Bootstrap 文件並修改其中一個示例。
以下是index.html頁面中的內容:
<!-- app/templates/index.html: Redesigned pagination links. -->
...
<nav aria-label="...">
<ul class="pager">
<li class="previous{% if not prev_url %} disabled{% endif %}">
<a href="{{ prev_url or '#' }}">
<span aria-hidden="true">←</span> Newer posts
</a>
</li>
<li class="next{% if not next_url %} disabled{% endif %}">
<a href="{{ next_url or '#' }}">
Older posts <span aria-hidden="true">→</span>
</a>
</li>
</ul>
</nav>
請注意,在這個實現中,當下一頁或上一頁方向上沒有更多內容時,我將應用禁用狀態,而不是隱藏下一頁或上一頁連結,這將使連結顯示為灰色。
類似的更改需要應用於user.html,我不會在這裡展示它。本章的下載包包含這些更改。
對比更改前後
要使用這些更改來更新您的應用程式,請下載本章的zip檔案並相應地更新您的模板。
下面你可以對比幾張美化前後的圖片來觀察轉變情況。請記住,在不更改一行應用程式邏輯的情況下實現了此更改!