Flask系列:模板

這個系列是學習《Flask Web開發:基于Python的Web應用開發實戰》的部分筆記

雖然可以在視圖中直接編寫 HTTP 頁面的內容,但是這種方式很原始。將與數據庫交互的業務邏輯,與生成響應的表現邏輯混在了一起。一方面不適合大型、復雜頁面的編寫、維護,結構不清晰,另外,由于業務邏輯通常由程序員完成,而表現邏輯由設計師完成,這樣雙方的工作會互相影響。

@app.route('/')
def index():
    return '<h1>Hello World!</h1>'

flask 支持 MVC 模型,由程序員在視圖中完成與數據庫的交互——業務邏輯(M),而顯示給客戶端的頁面在模板中定義(V),由設計師完成。

模板是一個包含響應文本的文件(通常是 HTML),其中包含用 占位變量 表示的動態部分, 具體值只在收到具體的請求后,通過上下文才能知道,模板中最主要的是前端技術,HTLM、CSS、JS 等。

模板引擎實現對模板的渲染,就是根據上下文,對模板中的占位變量,用真實值替換,形成最終的響應文件。

模板文件夾

默認情況下,Flask 在程序文件夾中的 templates 子文件夾中尋找模板。

模板的調用

flask 使用 jinjia2 模板引擎,為了便于使用,已經集成到 render_template 函數中,可以直接調用。

from flask import Flask, render_template

@app.route('/')
def index():
    return render_template('index.html')    # 注意,是包含 .html 后綴的完整文件名

@app.route('/user/<name>')
def user(name):
    return render_template('user.html', name=name)

第一個參數是模板的名稱,然后是 鍵/值 對,name=name左邊表示模板中的占位符,右邊是當前視圖中的變量。意思是,將當前視圖中變量name的值,賦值給模板中名為name的占位符,用于渲染。

變量

  • 表示

{{ name }}

占位符,告訴模板引擎,這個位置的值從渲染模板時傳遞的數據字典中獲取

  • 支持的變量類型

支持所有類型,字符串、整型、列表、字典 ......

  • 修改顯示樣式

通過使用過濾器,可以定制 變量的值 顯示的效果,比如 大小寫。{{ name | 過濾器 }}

過濾器列表

  • 模板變量

在模板中設置模板變量

{% set name = 'john' %}

控制結構

主要用于改變渲染流程

  • 條件控制

if...else...endif

判斷條件是否符合,并執行相應的語句

  • 循環:for...endfor

用于渲染一組元素

  • 宏:macro...endmacro

類似函數

定義一個宏,指定宏的名稱、參數,調用

{% macro x(y) %}
    ...
{% endmacro %}

{{ x(y) }}

如果需要在多個模板中復用,可以將宏的定義放入一個文件,‘macro.html’

{% macro x(y) %}
    ...
{% endmacro %}

然后導入使用

import 'macro.html' as macro

{{ macro.x(y) }}
  • 繼承:

如果多個頁面的大部分內容相同,可以定義一個母模板,包含相同的內容,然后子模板繼承內容,并根據需要進行部分修改

base.html,母模板,其中,用{% block title %}...{% endblock %}定義了可以由子模板替換的區域,title是區塊的名稱,可以有多個區塊

{% block title %}Hello{% endblock %}

在子模板中,聲明繼承的母模板,然后用{% block title %}...{% endblock %}指定替換哪個區塊的內容,并填入自己的內容。子模板中沒有指定的區塊,默認使用母模板的內容

{% extends "base.html" %}

{% block title %}john{% endblock %}

如果希望能夠保留母版的內容,并添加新內容,可以使用super()

{% extends "base.html" %}

{% block title %}
    {{ super() }}
    john
{% endblock %}

模板里面,不能同時有兩個{% extends " " %}語句,即使另一個被注釋了也不行

  • 包含:

如果多個網頁中都有一段內容相同,可以將相同的內容放入一個文件中comments.html,通過include導入

{% include 'comments.html' %}

bootstrap

Bootstrap是 Twitter 開發的一個開源框架,它提供的用戶界面組件可用于創建整潔且具有吸引力的網頁,而且這些網頁還能兼容所有現代 Web 瀏覽器。

一個名為Flask-Bootstrap的 Flask 擴展, 可以簡化在程序中集成 Bootstrap 的過程。

安裝:

$ pip install flask-bootstrap

初始化

從 flask.ext 命名空間中導入,然后把 程序實例傳入構造方法進行初始化。

run.py

from flask.ext.bootstrap import Bootstrap 
# ...
bootstrap = Bootstrap(app)

初始化 Flask-Bootstrap 之后,就可以在程序中使用一個包含所有 Bootstrap 文件的基模板。 這個模板利用 Jinja2 的模板繼承機制,讓程序擴展一個具有基本頁面結構的基模板,其中 就有用來引入 Bootstrap 的元素。

{% extends "bootstrap/base.html" %}

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

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

Jinja2 中 的 extends 指 令 從 Flask-Bootstrap 目錄中導入 bootstrap/base.html, 從而實現模板繼承。Flask-Bootstrap 中的基模板提供了一個網頁框架,引入了 Bootstrap 中的所有 CSS 和 JavaScript 文件。

virtualenv 環境中,目錄為lib/python2.7/site-packages/flask_bootstrap/templates/bootstrap/

基模板中定義了可在衍生模板中重定義的塊。block 和 endblock 指令定義的塊中的內容可添加到基模板中。

Bootstrap 官方文檔是很好的學習資源,有很多可以直接復制粘貼的示例。

自定義錯誤頁面

像常規路由一樣,Flask 允許程序使用基于模板的自定義錯誤頁面。最常見的錯誤代碼有兩個:404,客戶端請求未知頁面或路由時顯示;500,有未處理的異常時顯示。

自定義錯誤頁面

@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404

和視圖函數一樣,錯誤處理程序也會返回響應。它們還返回與該錯誤對應的數字狀態碼。 返回指定的數字狀態碼似乎沒有什么用 ?

url_for 生成連接

模板中可能有去往多個不同頁面的鏈接,例如導航條。

在模板中直接編寫簡單路由的 URL 鏈接不難,但對于包含可變部分的動態路由,在模板中構建正確的 URL 就很困難。而且,直接編寫 URL 會對代碼中定義的路由產生不必要的 依賴關系(hardcode)。如果修改 路由、視圖 的綁定關系, 模板中的鏈接可能會失效。

為了避免這些問題,Flask 提供了url_for()輔助函數,它可以使用程序URL映射中保存的信息,根據視圖名稱生成 URL。

例如,對于下面的視圖

@app.route('/')
def index():
    return '<h1>Hello World!</h1>'

調用 url_ for('index')得到的結果是/。調用url_for('index', _external=True)返回的則是絕對地址,是http://localhost:5000/

在程序內(模板、視圖中)生成連接程序內不同路由的鏈接時,使用相對地址就足夠了,瀏覽器、程序能夠根據當前的 URL 補全。但如果要在瀏覽器以外生成鏈接,例如在確認郵件中的鏈接,則必須使用絕對地址,否則誰也不知道前綴是什么。

使用url_for()生成鏈接時,將動態部分作為關鍵字參數傳入。例如,

@app.route('/user/<name>')
def user(name):
    return render_template('user.html', name=name)

url_for ('user', name='john', _external=True) 的返回結果是 http://localhost:5000/user/john

默認 _external 為 False,表示生成相對路徑;為 True 時,表示生成絕對路徑

函數能將任何額外參數添加到查詢字符串中。例如,

url_for('user', name='john', page=2)的返回結果是/user/john/?page=2

對于多層的模板結構,render_template 函數中需要添加從templates目錄下文件夾開始的路徑信息,render_template('main/index.html'),結構為templates/main/index.html,url_for() 需要用.隔開目錄,url_for('main.index.html')

Jinja2

更多jinja2 模板的語法

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容