Flask教程第十一章:美化

天降攻城獅發表於2019-02-22

本文轉載自:https://www.jianshu.com/p/2c3305d75bf4

這是Flask Mega-Tutorial系列的第十一部分,我將告訴你如何用基於Bootstrap使用者介面框架的新模板替換基礎的HTML模板。

你把玩Microblog應用也有一段時間了,所以我相信你已經注意到,我沒有花太多時間來美化它,說得更具體點,我根本沒有花時間。 所有的模板只使用了基礎樣式,沒有任何自定義的展現。 這對於我來說卻非常有用,因為我可以專注於應用的實際邏輯,不用分心於編寫好看的HTML和CSS程式碼。

但是我已經長期關注應用的後端部分一段時間了。 因此在本章中,我暫停一下後端的工作,並花點時間向你展示如何使應用看起來更加優雅和專業。

本章將與之前的章節略有不同,因為我不會像平常解說Python那樣,事無鉅細,一一道來,畢竟Python才是本教程的主要內容。 建立漂亮的網頁是一個很廣泛的話題,而與Python Web的後端開發很大程度上無關,因此我將討論一些基本的指導方針和想法,你可以通過重新設計應用的外觀來研究和學習它。

本章的GitHub連結為:BrowseZipDiff.

CSS框架

雖然我們可以爭辯說寫程式碼不容易,但是與那些必須讓網頁在所有Web瀏覽器上具有良好一致外觀的網頁設計師相比,我們的痛苦不值一提。 雖然近年來這種情況得到一定程度的緩解,但是在一些瀏覽器中仍然存在著晦澀的錯誤或奇怪的設定,這使得設計網頁的任務變得非常困難。 如果還需要相容螢幕限制裝置(諸如平板電腦和智慧手機)的瀏覽器,則更加困難。

如果你和我一樣,只是一個想建立出規範網頁的開發人員,沒有時間或興趣去學習底層機制並通過編寫原生HTML和CSS來實現它,那麼唯一可行的解決方案是使用CSS框架來簡化任務。 通過這種方式,你會失去一些創造性的自由,但另一方面,無需通過太多的功夫就可以讓網頁在所有瀏覽器中看起來都不錯。 CSS框架為普通型別的使用者介面元素提供了高階CSS類的集合,其中包含預定義樣式。 大多數這樣的框架還提供JavaScript外掛,以實現不能純粹使用HTML和CSS來完成的功能。

Bootstrap簡介

最受歡迎的CSS框架之一是由Twitter推出的Bootstrap。 如果你想看看這個框架可以設計的頁面型別,文件有一些示例

這些是使用Bootstrap來設定網頁風格的一些好處:

  • 在所有主流網頁瀏覽器中都有相似的外觀
  • 自動處理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例項。

# ...
from flask_bootstrap import Bootstrap

app = Flask(__name__)
# ...
bootstrap = Bootstrap(app)

在初始化外掛之後,bootstrap/base.html模板就會變為可用狀態,你可以使用extends子句從應用模板中引用。

但是,回顧一下,我已經使用了extends子句來繼承我的基礎模板,這使我可以將頁面的公共部分放在一個地方。 base.html模板定義了導航欄,其中包含幾個連結,並且還匯出了一個content塊。 應用中的所有其他模板都從基礎模板繼承,併為內容塊提供頁面的主要內容。

那麼我怎樣才能適配Bootstrap基礎模板呢? 解決方案是從使用兩個層級到使用三個層級。 bootstrap/base.html模板提供頁面的基本結構,其中引入了Bootstrap框架檔案。 這個模板為派生的模板定義了一些塊,例如titlenavbarcontent(參見塊的完整列表)。 我將更改base.html模板以從bootstrap/base.html派生,並提供titlenavbarcontent塊的實現。 反過來,base.html將為從其派生的模板匯出app_content塊以定義頁面內容。

下面你可以看到從Bootstrap基礎模板派生的base.html的程式碼。 請注意,此列表不包含導航欄的整個HTML,但你可以在GitHub上或下載本章的程式碼來檢視完整的實現。

app/templates/base.html:重新設計後的基礎模板。

{% 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:重新設計後的404錯誤模板。

{% 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::使用者註冊模板。

{% 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: 重新設計後的使用者動態子模板。

    <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: 重新設計後的分頁連結。

    ...
    <nav aria-label="...">
        <ul class="pager">
            <li class="previous{% if not prev_url %} disabled{% endif %}">
                <a href="{{ prev_url or `#` }}">
                    <span aria-hidden="true">&larr;</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">&rarr;</span>
                </a>
            </li>
        </ul>
    </nav>

請注意,在分頁連結的實現中,當某個方向沒有更多內容時,不是隱藏該連結,而是使用禁用狀態,這會使該連結顯示為灰色。

類似的更改需要應用於user.html,但我不打算展示在此處。 本章的下載包中包含這些更改。

對比

請下載本章的zip檔案並更新應用。

下面你可以對照幾張美化前後的圖片來觀察轉變情況。 請記住,這種轉變是在不改變一行應用邏輯程式碼的情況下實現的!

登入

主頁


相關文章