1. 程式人生 > >Flask Mega-Tutorial 中文教程 V2.0 第11章:整容

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後端開發很大程度上無關,但我將討論如何處理前端的一些基本指導和想法,並且您還將通過重新設計外觀來研究和學習它。

本章的GitHub連結是:BrowseZipDiff

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框架檔案。這個模板匯出了一些用於派生模板(如titlenavbarcontent)的塊(請參閱塊的完整列表)。我要更改base.html檔案模板,讓它繼承bootstrap/base.html檔案,並提供titlenavbarcontent塊。反過來,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">&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檔案並相應地更新您的模板。

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

ch12-login

ch12-index