1. 程式人生 > >Flask框架基礎(二)

Flask框架基礎(二)

##1 程式的基本結構 ###1.1初始化 所有Flask 程式都必須建立一個程式例項。Web 伺服器使用一種名為Web 伺服器閘道器介面(Web Server Gateway Interface,WSGI)的協議,把接收自客戶端的所有請求都轉交給這個物件處理。程式例項是Flask 類的物件。

from flask import Flask
app = Flask(__name__)

傳入Flask構造方法的第一個引數是模組或者包的名稱,我們應該使用特殊變數 __name __。 Python會根據所處的模組來賦予 __ name __變數相應的值,對於我們程式來說,這個值為app ###1.2註冊路由 客戶端(例如Web 瀏覽器)把請求傳送給Web 伺服器,Web 伺服器再把請求傳送給Flask 程式例項。程式例項需要知道對每個URL 請求執行哪些程式碼,所以儲存了一個URL 到Python 函式的對映關係。處理URL 和函式之間關係的程式稱為路由。

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

在這個程式中,app.route()裝飾器把根地址/和index()函式繫結起來,當用戶訪問這個URL時就會觸發index()函式。檢視函式index()返回 " Hello World! "

route()裝飾器的第一個引數是URL規則,用字串表示,必須以/開始。這裡的URL是相對的URL(又稱內部URL),即不包含域名的URL,以域名www.google.com為例,“/”對應的是根地址,即www.google.com,如果把URL規則改為“/maps”,則實際的絕對地址為

www.google.com/maps ######動態路由 如果你仔細觀察日常所用服務的某些URL 格式,會發現很多地址中都包含可變部分。例如, 你的Facebook 資料頁面的地址是http://www.facebook.com/, 使用者名稱(your-name)是地址的一部分。Flask 支援這種形式的URL,只需在route 修飾器中使用特殊的句法即可。下例定義的路由中就有一部分是動態名字:

@app.route('/user/<name>')
def user(name):
return '<h1>Hello, %s!</h1>' % name

###1.3啟動伺服器 程式例項用run 方法啟動Flask 整合的開發Web 伺服器:

if __name__ == '__main__':
app.run(debug=True)

__ name__==’__ main__'是Python 的慣常用法,在這裡確保直接執行這個指令碼時才啟動開發Web 伺服器。如果這個指令碼由其他指令碼引入,程式假定父級指令碼會啟動不同的伺服器,因此不會執行app.run()。 ###1.4完整的程式

示例1.4 hello.py:一個完整的Flask 程式

from flask import Flask
app = Flask(__name__)

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

@app.route('/user/<name>')
def user(name):
    return '<h1>Hello, %s!</h1>' % name

if __name__ == '__main__':
    app.run(debug=True)

###1.4 異常捕獲 使用裝飾器的形式去捕獲指定的錯誤碼和異常

@app.errorhandler(404)
def page_not_found(error):
	return	'404'

###1.5請求鉤子 為了讓每個檢視函式避免編寫重複功能的程式碼,Flask提供了通用設施的功能,即請求鉤子。 請求鉤子是通過裝飾器的形式實現,Flask支援如下四種請求鉤子:

  • before_first_request:註冊一個函式,在處理第一個請求之前執行。
  • before_request:註冊一個函式,在每次請求之前執行。
  • after_request:註冊一個函式,如果沒有未處理的異常丟擲,在每次請求之後執行。
  • teardown_request:註冊一個函式,即使有未處理的異常丟擲,也在每次請求之後執行。 – ##2 模板 模板是一個包含響應文字的檔案,其中包含用佔位變量表示的動態部分,其具體值只在請求的上下文中才能知道。使用真實值替換變數,再返回最終得到的響應字串,這一過程稱為渲染。為了渲染模板,Flask 使用了一個名為Jinja2 的強大模板引擎。 ###2.1 Jinja2模板引擎
  1. Jinjia2是由python實現的
  2. 是Flask內建的模板語言
  3. 參照Django設計思想設計的,跟Django差不多 ####2.1.1渲染模板 預設情況下,Flask 在程式資料夾中的templates 子資料夾中尋找模板。Flask提供的
from flask import Flask, render_template
# ...
@app.route('/')
def index():
    return render_template('index.html')
@app.route('/user/<name>')
def user(name):
    return render_template('user.html', name=name)

示例 templates/index.html:Jinja2 模板

<h1>Hello World!</h1>

示例

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

render_template 函式封裝了該模板引擎 render_template 函式的第一個引數是模板的檔名,後面的引數都是鍵值對,表示模板中變數對應的真實值

###2.1.2 變數 在模板中使用的{{ name }} 結構表示一個變數,它是一種特殊的佔位符,告訴模 板引擎這個位置的值從渲染模板時使用的資料中獲取。

可以使用過濾器修改變數,過濾器名新增在變數名之後,中間使用豎線分隔。例如,下述模板以首字母大寫形式顯示變數name 的值:

Hello, {{ name|capitalize }}

Jinja2 提供的部分常用過濾器

表 Jinja2變數過濾器

過濾器名 說明
safe 渲染值時不轉義
capitalize 把值的首字母轉換成大寫,其他字母轉換成小寫
lower 把值轉換成小寫形式
upper 把值轉換成大寫形式
title 把值中每個單詞的首字母都轉換成大寫
trim 把值的首尾空格去掉
striptags 渲染之前把值中所有的HTML 標籤都刪掉

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

  • 條件控制:
{% if user %}
    Hello, {{ user }}!
{% else %}
    Hello, Stranger!
{% endif %}
  • 迴圈控制:
<ul>
    {% for comment in comments %}
        <li>{{ comment }}</li>
    {% endfor %}
</ul>
  • 巨集
<!--巨集的定義-->
{ % macro render_comment(comment) % }
    <li>{{ comment }}</li>
{ % endmacro % }
<!--巨集的使用-->
<ul>
    { % for comment in comments % }
        <!--巨集呼叫-->
        {{ render_comment(comment) }}
    { % endfor % }
</ul>

####模板程式碼複用 在模板中,可能會遇到以下問題

  1. 多個模板具有完全相同的頂部和底部內容

  2. 多個模板中具有相同的模板程式碼內容,但是內容中部分值不一樣

  3. 多個模板中具有完全相同的 html 程式碼塊內容

像遇到這種情況,可以使用 JinJa2 模板中的 巨集、繼承、包含來進行實現

#####模板繼承

標籤定義的內容

{% block %} {% endblock %}

模板繼承是為了重用模板中的公共內容。一般Web開發中,繼承主要使用在網站的頂部選單、底部。這些內容可以定義在父模板中,子模板直接繼承,而不需要重複書寫。

首先建立一個名為base.html 的基模板
<html>
<head>
    {% block head %}
    <title>{% block title %}{% endblock %} - My Application</title>
    {% endblock %}
</head>
<body>
    {% block body %}
    {% endblock %}
</body>
</html>

block 標籤定義的元素可在衍生模板中修改。在本例中,我們定義了名為head、title 和 body 的塊。注意,title 包含在head 中。下面這個示例是基模板的衍生模板:

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

extends 指令宣告這個模板衍生自base.html。在extends 指令之後,基模板中的3 個塊被 重新定義,模板引擎會將其插入適當的位置。注意新定義的head 塊,在基模板中其內容不 是空的,所以使用super() 獲取原來的內容。 ###2.2 Flask-Bootstrap Bootstrap(http://getbootstrap.com/)是Twitter 開發的一個開源框架,它提供的使用者介面組 件可用於建立整潔且具有吸引力的網頁,而且這些網頁還能相容所有現代Web 瀏覽器。 Bootstrap 是客戶端框架,因此不會直接涉及伺服器。伺服器需要做的只是提供引用了 Bootstrap 層疊樣式表(CSS) 和JavaScript 檔案的HTML 響應, 並在HTML、CSS 和 JavaScript 程式碼中例項化所需元件。這些操作最理想的執行場所就是模板。

  • 初始化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 %}

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

@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

###2.4 連結 在模板中直接編寫簡單路由的 URL 連結不難,但對於包含可變部分的動態路由,在模板中構建正確的 URL 就很困難。而且,直接編寫 URL 會對程式碼中定義的路由產生不必要的依賴關係。如果重新定義路由,模板中的連結可能會失效。Flask 提供了 url_for() 輔助函式,它可以使用程式 URL 對映中儲存的資訊生成 URL。 ###2.5 靜態檔案 用靜態檔案,例如 HTML程式碼中引用的圖片、JavaScript 原始碼檔案和 CSS。預設設定下,Flask 在程式根目錄中名為 static 的子目錄中尋找靜態檔案。如果需要,可在static 資料夾中使用子資料夾存放檔案。 如索引圖示的位置{{ url_for('static', filename = 'favicon.ico') }} flask