Flask是一個相對於Django而言輕量級的Web框架。css
和Django大包大攬不一樣,Flask創建於一系列的開源軟件包之上,這其中 最主要的是WSGI應用開發庫Werkzeug和模板引擎Jinja:html
策略 :werkzeug和Jinja這兩個庫和Flask同樣,都是pocoo團隊開發的。這 或許體現了pocoo與Django競爭時關於生態的一種策略,這種策略的天然 延伸是Flask框架中沒有包含數據庫方面的構件,不管ORM仍是其餘。jquery
關注點 :Flask是一個WSGI應用框架,這意味着咱們進行Flask開發時,不須要 關注網絡方面的操做,Flask應用的入口是封裝過的網絡請求包,出口是 網絡響應,咱們僅須要關注這個階段內的處理邏輯。web
WSGI服務器 :Flask雖然內置了簡單的WSGI服務器,但其性能僅僅適用於開發期的調試。 Flask官網推薦了多種WSGI服務器,實現方式從多進程到多線程到協程, 這方面的選擇咱們在本課程中將不涉及。數據庫
REST適應性 :雖然Flask和Django同樣,最初的出發點都是服務端的動態網頁應用。但 Flask的設計使之也至關適用於面向資源的REST架構,在愈來愈移動化 而且單頁應用愈來愈重要的WEB開發領域,這是Flask相對於Django至關 大的優點。json
編寫一個基於Flask的hello world至關容易:flask
一、導入Flask類服務器
from flask import Flask
Flask類是Flask框架的核心類,它實現了WSGI應用規範。網絡
二、建立Flask實例多線程
app = Flask(__name__)
Flask構造函數的第一個參數指定一個引入名/import_name。Flask框架 使用這個名字進行靜態資源、模板、錯誤信息的定位。除非你清楚的理解它的 做用,一般狀況下,咱們總應該使用特殊變量__name__。
Flask實例是可調用的(具備__call__方法),這個實例能夠直接對接 WSGI服務器。
三、註冊路由
@route('/') def index(): return 'Hello,Flask!'
註冊路由就是創建URL規則和處理函數之間的關聯。Flask框架依賴於路由 完成HTTP請求的分發。
路由中的函數被稱爲視圖函數,其返回值將做爲HTTP響應的正文內容。
四、對接並啓動WSGI服務器
Flask封裝了一個簡單的開發用WSGI服務器,咱們能夠經過調用run() 啓動服務器運行:
app.run(host='0.0.0.0',port=80)
路由是MVC架構的Web框架中至關重要的一個概念,也是本節課程的重點。
顧名思意,路由就是在迷茫中找出一條路的意思。在Flask框架中,路由就表示爲用戶請求的URL找出其對應的處理函數之意。
在本節課程,咱們將主要從如下幾個方面講解Flask框架中的路由:
如何爲應用註冊路由? 如何爲路由指定其支持的HTTP方法? 如何匹配動態URL? 如何對URL中的變量類型進行過濾? 如何理解訪問點/endpoint? 如何爲應用設定靜態路由? 如何避免硬編碼指向其餘視圖的URL?
在Flask應用中,路由是指用戶請求的URL與視圖函數之間的映射。Flask框架 根據HTTP請求的URL在路由表中匹配預約義的URL規則,找到對應的視圖函數, 並將視圖函數的執行結果返回WSGI服務器:
可見路由表在Flask應用中處於至關核心的位置。路由表的內容是由應用開發者填充。
route裝飾器 :可使用Flask應用實例的route裝飾器將一個URL規則綁定到 一個視圖函數上。
例如,下面的示例將URL規則/test綁定到視圖函數test()上:
@app.route('/test') def test(): return 'this is response'
若是這個應用部署在主機ezhost.com的根目錄下,那麼當用戶訪問:
http://ezhost.com/test
Flask框架就會調用咱們的test()函數,其返回結果就傳遞給WSGI服務器發送給訪問者。
add_url_rule() :另外一種等價的寫法是使用Flask應用實例的add_url_route()方法。 下面的示例註冊了一個與前例相同的路由:
def test(): return 'this is response' app.add_url_route('/test',view_func=test)
其實,route裝飾器內部也是經過調用add_url_route()方法實現的路由註冊。 可是顯然,使用裝飾器使代碼看起來更優雅一些。
默認狀況下,Flask路由僅支持HTTP的GET請求。可使用methods關鍵字參數,在註冊 路由時顯式地聲明視圖方法支持的HTTP方法。
例如,下面的示例將URL規則/auth綁定到視圖函數v_auth(),這個路由僅支持POST方法:
@app.route('/auth',methods=['POST']) def v_auth():pass
指定多種HTTP方法支持
關鍵字參數methods的類型爲list,所以能夠同時指定多種HTTP方法。
下面的示例中,使URL規則/user同時支持POST方法和GET方法:
@app.route('/user',methods=['POST','GET']) def v_users(): if request.method == 'GET': return ... # 返回用戶列表 if request.method == 'POST' return ... #建立新用戶
這個特性使Flask很是易於開發REST架構的後臺服務,而不只僅侷限於傳統的動態網頁。
有時咱們須要將同一類URL映射到同一個視圖函數處理,好比,使用同一個視圖函數 來顯示不一樣用戶的我的檔案。咱們但願如下的URL均可以分發到同一個視圖函數:
在Flask中,能夠將URL中的可變部分使用一對小括號<>聲明爲變量, 併爲視圖函數聲明同名的參數:
@app.route('/user/<uname>') def v_user(uname): return '%s\'s Profile' % uname </uname>
在上面的示例中,URL規則中的<uname>表示這部分是可變的,Flask將提取用戶請求的 URL中這部分的內容,並做爲視圖函數v_user()的uname參數進行調用。
考慮下面的示例,咱們但願經過HTTP共享文件夾/var/readonly中的文件:
/var /readonly /a.txt /b.txt /repo /c.txt /d.txt
簡單思考一下就有答案了。咱們能夠構造URL規則/file/<fname>,而後直接 讀取文件內容返回給用戶。註冊以下的路由:
@app.route('/file/<fname>') def v_file(fname): fullname = os.path.join('/var/readonly',fname) f = open(fullname) cnt = f.read() f.close() return cnt </fname>
測試結果代表,/file/a.txt和/file/b.txt都沒有問題,可是/file/repo/c.txt和 /file/repo/d.txt卻會失敗。
這是由於,默認狀況下,在URL規則中的變量被視爲不包含/的字符串。/file/repo/c.txt 是沒有辦法匹配URL規則/file/<fname>的。
可使用內置的path轉換器告訴Flask框架改變這一默認行爲。path轉換器容許 規則匹配包含/的字符串:
@app.route('/file/<path:fname>') </path:fname>
在Flask中,轉換器/converter用來對從URL中提取的變量進行預處理,這個過程 發生在調用視圖函數以前。Flask預置了四種轉換器:
咱們一直強調,路由的做用是根據請求的URL,找到對應的視圖函數。這沒錯,可是在 Flask框架中,請求任務的分發並非直接從用戶請求的URL一步定位到視圖函數, 二者之間隔着一個訪問點/endpoint。
如下面的代碼爲例,咱們看Flask怎樣實現請求的分發:
@app.route('/home') def home():pass
在Flask內部使用兩張表維護路由:
以用戶訪問URL/home爲例,Flask將首先利用url_map找到所請求URL對應的 endpoint,即訪問點home,而後再利用view_functions表查找home這個訪問點 對應的視圖函數,最終匹配到函數home():
默認訪問點 :當咱們使用route裝飾器註冊路由時,默認使用被裝飾函數的 函數名(name)做爲訪問點,所以,你看到上面的表中,路由中的訪問點爲home。
自定義訪問點 :能夠在使用route裝飾器或調用add_url_rule()方法註冊路由時,使用 endpoint關鍵字參數改變這一默認行爲:
@app.route('/home',endpoint='whocare') def home():pass
此時的兩張路由表將變成這樣:
當建立應用實例時,Flask將自動添加一條靜態目錄路由,其訪問點 始終被設置爲static,URL規則默認被設置爲/static,本地路徑默認被 設置爲應用文件夾下的static子文件夾:
+------------------------------------------------------------+ | url rule | endpoint | view_function | | /static | static | Flask.send_static_file | +------------------------------------------------------------+ 若是你的應用目錄以下:
/app /web.py /static /main.css /jquery.min.js
那麼啓動應用後就能夠經過URL/static/main.css訪問static文件夾下的main.css了。
除了訪問點被固定爲static,靜態目錄的URL規則和本地目錄都是能夠根據應用狀況進行調整。
改變默認的本地路徑 :能夠在建立應用對象時使用關鍵字參數static_folder改變 默認的靜態文件夾。例如,你的靜態文件都存放在應用下的assets目錄下, 那麼能夠按以下的方式建立應用對象:
app = Flask(name,static_folder='assets') 也可使用一個絕對路徑:
app = Flask(name,static_folder='/var/www/static') 改變默認的本地路徑並不會對路由表產生影響。
改變默認的URL規則 : 若是不喜歡靜態目錄URL/static,也能夠在建立應用 對象時使用關鍵字參數static_url_path換一個別的名字。
下面的示例中,將應用下的assets文件夾註冊爲靜態目錄/assets:
app = Flask(name,static_folder='assets',static_url_path='/assets') 當應用運行後,經過URL/assets/main.css就能夠訪問assets文件夾下的 main.css文件了。
這時的路由表變化爲:
+------------------------------------------------------------+ | url | endpoint | view_function | | /assets | static | Flask.send_static_file | +------------------------------------------------------------+
在一個實用的視圖中,不可避免地存在指向其餘視圖的連接。在以前的課程示例中,咱們 都是在視圖函數中這樣硬編碼這些連接URL的:
@app.route('/') def v_index(): return '<a href="/tech">tech</a>' @app.route('/tech') def v_tech():pass
大部分狀況下這種硬編碼URL是能夠工做的。但若是這個應用被掛在WSGI服務器的一個 子路徑下,好比:/app1,那麼用戶訪問URL/tech是不會成功的,這時應當訪問/app1/tech 才能夠正確地路由到視圖函數v_tech()。
咱們應當使用訪問點讓Flask框架幫咱們計算連接URL。簡單地給url_for()函數傳入 一個訪問點,它返回將是一個可靠的URL地址:
@app.route('/') def v_index(): print url_for('v_contacts') # /contact return 'see console output!' @app.route('/contact') def v_contacts():pass
添加查詢參數 : 使用關鍵字參數,能夠在構造的URL中生成查詢串。下面的調用將生成 /contact?format=json
@app.route('/') def v_index(): print url_for('v_contacts',format='json') return '' @app.route('/contact') def v_contacts():pass
添加URL變量 : 若是指定訪問點對應的視圖函數接收參數,那麼關鍵字參數將生成對應的參數URL。下面的 示例將生成/contact/Julia?format=html:
@app.route('/') def v_index(): print url_for('v_contact',name='Julia',format='html') return '' @app.route('/contact/<name>') def v_contact(name):pass </name>
添加錨點 :使用_anchor關鍵字能夠爲生成的URL添加錨點。下面的示例將生成URL /contact#part2
@app.route('/') def v_index(): print url_for('v_contacts',_anchor='part2') @app.route('/contact') def v_contacts():pass
外部URL : 默認狀況下,url_for()生成站內URL,能夠設置關鍵字參數_external 爲True,生成包含站點地址的外部URL。下面的示例將生成URLhttp://<x.y.z>/contacts:
@app.route('/') def v_index(): print url_for('v_contacts',_external=True) @app.route('/contact') def v_contacts():pass
更多內容如請求應答、核心機制、數據庫相關、組件以及相應的示例和練習能夠去這裏==>http://www.hubwiz.com/course/562427361bc20c980538e26f/