1. 程式人生 > >flask學習筆記(-模板)

flask學習筆記(-模板)

為什麼使用模板

檢視函式的作用很明確,即生成請求的響應。但 Flask 檢視函式的兩個完全獨立的作用(處理邏輯和頁面)卻被融在一起。
例如,使用者在網站中註冊了一個新賬戶。使用者在表單中輸入電子郵件地址和密碼,然後點選提交按鈕。伺服器接收到包含使用者輸入資料的請求,然後 Flask 把請求分發到處理註冊請求的檢視函式。這個檢視函式需要訪問資料庫,新增新使用者,然後生成響應回送瀏覽器。這兩個過程分別稱為業務邏輯表現邏輯
Flask,使用模板將這兩個邏輯分離。這樣檢視函式可以專注於處理業務邏輯,而表現邏輯則交給Flask的Jinjia2的模板引擎來處理。

jinjia2模板引擎

官方文件

包括API,沙箱,模板設計者文件。
{% … %} for Statements
{{ … }} for Expressions to print to the template output
{# … #} for Comments not included in the template output
# … ## for Line Statements
建立user模板

<h1> Hello, {{ name }}! </h1>

渲染模板

Flask在程式資料夾的templates子資料夾中尋找模板。
渲染模板呼叫:render_template('user.html', var_key=var_value)

。 render_template 函式把 Jinja2 模板引擎整合到了程式中。第一個引數是模板的檔名。隨後的引數都是鍵值對,表示模板中變數對應的真實值。左邊的“var_key”表示引數名,就是模板中使用的佔位符;右邊的“var_value”是當前作用域中的變數,表示同名引數的值。

變數

{{ name }} 結構表示一個變數,它是一種特殊的佔位符,告訴模板引擎這個位置的值從渲染模板時使用的資料中獲取。
Jinja2 能識別所有型別的變數,甚至是一些複雜的型別,例如列表、字典和物件。

<p>a dictionary: {{ mydict['key'] }}.</p
>
<p>a list: {{ mylist[3] }}.</p> <p>a list, with a variable index: {{ mylist[myintvar] }}.</p> <p>an object's method: {{ myobj.somemethod() }}.</p>

過濾器變數可以通過 過濾器 修改。過濾器與變數用管道符號( | )分割,並且也 可以用圓括號傳遞可選引數。多個過濾器可以鏈式呼叫,前一個過濾器的輸出會被作為 後一個過濾器的輸入。例如 {{ name|striptags|title }} 會移除 name 中的所有 HTML 標籤並且改寫 為標題樣式的大小寫格式。內建過濾器清單

控制結構

Jinja2 提供了多種控制結構,可用來改變模板的渲染流程。

  • 條件控制。
{ % if user % }
    Hello, {{ user }}!
{ % else % }
    Hello, Stranger!
{ % endif % }
  • 迴圈控制
<ul>
{ % for comment in comments % }
    <li>{{ comment }}</li>
{ % endfor % }
</ul>
  • 巨集
    巨集類似於 Python 程式碼中的函式。
<!--巨集的定義-->
{ % macro render_comment(comment) % }
    <li>{{ comment }}</li>
{ % endmacro % }
<!--巨集的使用-->
<ul>
    { % for comment in comments % }
        <!--巨集呼叫-->
        {{ render_comment(comment) }}
    { % endfor % }
</ul>
  • 包含模板
    需要在多處重複使用的模板程式碼片段可以寫入單獨的檔案,再包含在所有模板中,以避免重複:
{ % include 'common.html' as common% }
{{common.XXXX}}
  • 模板繼承
    它類似於 Python 程式碼中的類繼承。
    首先,定義基模板。如base.html
<html>
<head>
{ % block head % }
    <title>{ % block title % }{ % endblock % } - My Application</title>
{ % endblock % }
</head>
<body>
    { % block body % }
    { % endblock % }
</body>
</html>

定義衍生模板。

{ % extends "base.html" % }
{ % block title % }Index{ % endblock % }
{ % block head % }
    {{ super() }}
    <style></style>
{ % endblock % }
{ % block body % }
    <h1>Hello, World!</h1>
{ % endblock % }

{% extend %} 標籤是這裡的關鍵。它告訴模板引擎這個模板“繼承”另一個模板。 當模板系統對這個模板求值時,首先定位父模板。 extends 標籤應該是模板中的第一個 標籤。它前面的所有東西都會按照普通情況打印出來,而且可能會導致一些困惑。
extends 指令宣告這個模板衍生自 base.html。在 extends 指令之後,基模板中的 3 個塊被重新定義,模板引擎會將其插入適當的位置。注意新定義的 head 塊,在基模板中其內容不是空的,所以使用 super() 獲取原來的內容,呼叫 super 來渲染父級塊的內容。這會返回父級塊的結果。

設計模板

使用Flask-Bootstrap

  • 安裝pip install flask-bootstrap
  • 初始化Flask-Bootstrap
from flask.ext.bootstrap import Bootstrap
# ...
bootstrap = Bootstrap(app)

初始化 Flask-Bootstrap 之後,就可以在程式中使用一個包含所有 Bootstrap 檔案的基模板。這個模板利用Jinja2的模板繼承機制,讓程式擴充套件一個具有基本頁面結構的基模板,其中就有用來引入 Bootstrap 的元素。官方教程

{% extends "bootstrap/base.html" %}<!--extends 指 令 從 Flask-Bootstrap中匯入bootstrap/base.html,實現模板繼承。 -->

{% block title %}Flasky{% endblock %}

{% block navbar %}
<div class="navbar navbar-inverse" role="navigation">
    <div class="container">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="/">Flasky</a>
        </div>
        <div class="navbar-collapse collapse">
            <ul class="nav navbar-nav">
                <li><a href="/">Home</a></li>
            </ul>
        </div>
    </div>
</div>
{% endblock %}

{% block content %}
<div class="container">
    <div class="page-header">
        <h1>Hello, {{ name }}!</h1>
    </div>
</div>
{% endblock %}

定義錯誤頁面

如果你在瀏覽器的位址列中輸入了不可用的路由,那麼會顯示一個狀態碼為 404 的錯誤頁面。現在這個錯誤頁面太簡陋、平庸,而且樣式和使用了 Bootstrap 的頁面不一致。

  • 定義錯誤處理函式。
    與檢視函式類似,只不過使用不同的修飾器@app.errorhandler(error_code)
@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404
@app.errorhandler(500)
def internal_server_error(e):
    return render_template('500.html'), 500
  • 編寫對應的模板檔案

連結

在模板中直接編寫簡單路由的 URL 連結不難,但對於包含可變部分的動態路由,在模板中構建正確的 URL 就很困難。而且,直接編寫 URL 會對程式碼中定義的路由產生不必要的依賴關係。如果重新定義路由,模板中的連結可能會失效。Flask 提供了 url_for() 輔助函式,它可以使用程式 URL 對映中儲存的資訊生成 URL。

靜態檔案

用靜態檔案,例如 HTML程式碼中引用的圖片、JavaScript 原始碼檔案和 CSS。預設設定下,Flask 在程式根目錄中名為 static 的子目錄中尋找靜態檔案。如果需要,可在static 資料夾中使用子資料夾存放檔案。
如索引圖示的位置{{ url_for('static', filename = 'favicon.ico') }}

Flask-Moment本地化日期和時間

  • 安裝
pip install flask-moment
  • 初始化
from flask.ext.moment import Moment
moment = Moment(app)
  • 引入 moment.js 庫
{ % block scripts % }
{{super()}}
{{moment.include_moment() }}
{ %endblock % }
  • 加入一個 datetime 變數
from datetime import datetime
@app.route('/')
def index():
    return render_template('index.html', current_time=datetime.utcnow())
  • 渲染時間
<p>The local date and time is {{ moment(current_time).format('LLL') }}.</p>