Flask系列:工作流程

這個系列是學習《Flask Web開發(fā):基于Python的Web應用開發(fā)實戰(zhàn)》的部分筆記

客戶端——web 服務器——WSGI——application

客戶端發(fā)送 HTTP 請求,web 服務器在一個地址的端口上等待接收抵碟,一旦收到仪缸,會將請求通過 WSGI 交給 application 處理逸月,application 就是 flask 框架編寫的應用可帽,application 對消息處理后,也通過 WSGI 返回 HTTP 響應給 web 服務器装哆,由服務器發(fā)送給客戶端台颠。

所有 Flask 程序都必須創(chuàng)建一個程序實例,實例是 Flask 類的對象

安裝

$ pip install flask
Collecting flask
Collecting itsdangerous>=0.21 (from flask)
Collecting Werkzeug>=0.7 (from flask)
  Using cached Werkzeug-0.11.2-py2.py3-none-any.whl
Collecting Jinja2>=2.4 (from flask)
  Using cached Jinja2-2.8-py2.py3-none-any.whl
Collecting MarkupSafe (from Jinja2>=2.4->flask)
Installing collected packages: itsdangerous, Werkzeug, MarkupSafe, Jinja2, flask
Successfully installed Jinja2-2.8 MarkupSafe-0.23 Werkzeug-0.11.2 flask-0.10.1 itsdangerous-0.24

創(chuàng)建實例:

run.py

from flask import Flask
app = Flask(__name__)

Flask 函數(shù)需要指定一個參數(shù)裸影,是程序主模塊或包的名字挣轨,大多數(shù)情況下,__name__就是需要的值轩猩。

Flask 用這個參數(shù)決定程序的根目錄,以便稍后能夠找到相對于程序根目錄的資源文件卷扮。

web 服務器

常見的有 uWSGI、Nginx均践、gunicorn 等

flask 集成了一個開發(fā)用的web服務器晤锹,同一時間只能處理一個請求

使用 flask 集成的服務器

run.py

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

debug = True, 調試模式,激活調試器彤委,當一些文件修改保存后鞭铆,會自動重新加載,而且出錯時焦影,能夠顯示足夠的提示信息车遂,具體到運行哪個文件的哪一行產生的錯誤,錯誤原因是什么斯辰。正因為會提供豐富的后臺信息舶担,所以強烈建議不要在生產環(huán)境中開啟。

運行

$ python run.py
 * Running on http://127.0.0.1:5000/
 * Restarting with reloader

WSGI

web 服務器和 web 框架 有很多種椒涯,并不總是能互相配合工作柄沮,那就要想辦法在它們之間搭建一個溝通的橋梁回梧,讓它們能正撤掀瘢互發(fā)消息,于是出現(xiàn)了 WSGI 規(guī)范狱意,規(guī)定了 web 服務器將客戶端的消息發(fā)送給 application 湖苞,以及 application 將處理后的消息發(fā)送給服務器的方法,這個規(guī)范在PEP 333中定義详囤。

flask 對消息的處理

上下文

在多線程服務器中财骨,定義了一個線程池,由多個線程同時處理不同客戶的不同請求(并發(fā))藏姐,當收到請求后隆箩,會選一個線程進行處理。flask 使用 程序/請求 上下文羔杨,臨時把某些對象在一個線程中設置為“全局可訪”捌臊,這樣既不會干擾其他線程,又使得所有視圖都能夠訪問這些對象兜材,并處理請求理澎。flask 收到請求后逞力,在將請求交給線程之前,會 激活/推送 上下文糠爬,建立環(huán)境寇荧,上下文的內容來自 web 服務器 通過 WSGI 發(fā)給 application 的消息,當請求處理完成后执隧,再刪除上下文揩抡。

在 Flask 中有兩種上下文: 程序上下文 和 請求上下文 全局變量

| 變量名 | 上下文說明 |
|---|---|---|
| current_app | 當前激活程序的程序實例 |
| g | 處理請求時用作臨時存儲的對象。每次請求都會重置這個變量 |
| request | 請求對象,封裝了客戶端發(fā)出的 HTTP 請求中的內容 |
| session | 用戶會話,用于存儲請求之間需要“記住”的值的詞典 |

路由殴玛、視圖函數(shù)

  • URL 映射

創(chuàng)建視圖時捅膘,會將 URL、HTTP 方法 和特定的視圖進行綁定滚粟,建立URL 映射

run.py

@app.route('/')  # 使用程序實例提供的`app.route`修飾器,把函數(shù)與URL綁定
def index():
    return '<h1>Hello World!</h1>'

用瀏覽器訪問http://localhost:5000/

查看URL 映射

>>> from run import app
>>> app.url_map
Map([<Rule '/' (HEAD, POST, OPTIONS, GET) -> index>,
 <Rule '/user/<username>' (HEAD, OPTIONS, GET) -> main.user>])
>>>

GET寻仗、POST 是請求方法,由路由進行處理凡壤。Flask 為每個路由都指 定了請求方法,這樣不同的請求方法發(fā)送到相同的 URL 上時,會使用不同的視圖函數(shù)進 行處理署尤。HEAD 和 OPTIONS 由 Flask 自動處理。

當線程收到 HTTP 請求后亚侠,在URL映射中尋找相應 URL曹体、HTTP方法 對應的視圖,由該視圖進行處理硝烂,并返回響應給 web 服務器箕别,發(fā)送給客戶端。

某些 URL 格式,會發(fā)現(xiàn)很多地址中都包含可變部分滞谢,F(xiàn)lask 支持這種形式的 URL,只需在 route 修飾器中使用特殊的句法即可

  • 關鍵字參數(shù)
http://localhost:5000/user/john

@app.route('/user/<name>') # 對 url 中串稀,/user/ 后面的內容進行匹配、截取狮杨,賦值給變量 name母截,默認匹配字符串,可以指定類型橄教。例如清寇,/user/<int:id> 只匹配 id 為整數(shù)的 URL
def user(name): # 變量 name 作為參數(shù)傳遞給函數(shù) user
    print name
  • 額外參數(shù)

作為 查詢字符串(url 中問號后面的),這個參數(shù)可從 request.args 字典中讀取

http://127.0.0.1:5000/index?page=2

@app.route('/index')
def index():
    page = request.args.get('page', 1, type=int)

print request.args

ImmutableMultiDict([('page', u'2')])

page=request.args.get('page', 1, type=int) 從 url 獲取 鍵為 page 的 值轉換為整形护蝶,如果沒有 或 轉換失敗华烟,默認為 1

鉤子

在將請求交給視圖處理前,或將視圖處理的結果返回給 web 服務器前持灰,可以調用鉤子盔夜,對 請求/響應 進行處理。例如,對于一個用戶的請求比吭,檢查這個用戶的賬號有沒有通過郵箱確認绽族,如果沒有,對某些頁面的訪問會被禁止訪問衩藤,重定向到一個特定的頁面吧慢,而其他頁面正常訪問。

請求鉤子使用修飾器實現(xiàn)赏表。Flask 支持以下 4 種鉤子:

  1. before_first_request:注冊一個函數(shù),在處理第一個請求之前運行检诗。
  2. before_request:注冊一個函數(shù),在每次請求之前運行。
  3. after_request:注冊一個函數(shù),如果沒有未處理的異常拋出,在每次請求之后運行瓢剿。
  4. teardown_request:注冊一個函數(shù),即使有未處理的異常拋出,也在每次請求之后運行逢慌。

響應

Flask 調用視圖函數(shù)后,會將其返回值作為響應的內容。大多數(shù)情況下,響應就是一個簡單的字符串,作為 HTML 頁面(也就是 HTTP 的 body)回送客戶端间狂。

  • 元組

但 HTTP 協(xié)議需要的不僅是作為請求響應的字符串攻泼。HTTP 響應中一個很重要的部分是狀態(tài)碼,Flask 默認設為 200,這個代碼表明請求已經(jīng)被成功處理。如果視圖函數(shù)返回的響應需要使用不同的狀態(tài)碼,那么可以把數(shù)字代碼作為第二個返回值,添加到響應文本之后鉴象。

@app.route('/')
def index():
    return '<h1>Bad Request</h1>', 400

視圖函數(shù)返回的響應還可接受第三個參數(shù),這是一個由首部(header)組成的字典 ,可以 添加到 HTTP 響應中忙菠。

  • Response 對象

如果不想返回由 1 個、2 個或 3 個值組成的元組,Flask 視圖函數(shù)還可以使用 make_response() 產生并直接返回完整的Response 對象纺弊。make_response() 函數(shù)可以接受 1 個牛欢、2 個或 3 個參數(shù)(和視圖函數(shù)的返回值一樣),并返回一個Response 對象。有時我們需要在視圖函數(shù)中產生Response 對象,然后在Response 對象上調用各種方法,進一步 設置響應 淆游。

from flask import make_response
     @app.route('/')
     def index():
         response = make_response('<h1>This document carries a cookie!</h1>')
         response.set_cookie('answer', '42') # 設置 cookie
         return response
  • 重定向

有一種名為重定向的特殊響應類型傍睹。這種響應沒有頁面文檔, 只是用于告訴瀏覽器一個新地址,以便加載新頁面犹菱。重定向經(jīng)常在 Web 表單中使用拾稳。

重定向經(jīng)常使用 302 狀態(tài)碼表示,指向的地址由 HTTP 的Location 首部提供。重定向響應可以使用 3 個值形式的返回值生成,也可在 Response 對象中設定已亥。不過,由于使用頻繁,Flask 提供了redirect() 輔助函數(shù), 用于生成這種響應熊赖。

from flask import redirect

@app.route('/')
def index():
    return redirect('http://www.example.com')
  • 異常跳出

還有一種特殊的響應由abort 函數(shù)生成,用于處理錯誤来屠。

from flask import abort

@app.route('/user/<id>')
    def get_user(id):
        user = load_user(id)
        if not user:         # 如果用戶不存在
            abort(404)       # 拋出異常
        return '<h1>Hello, %s</h1>' % user.name

注意,abort 會直接跳出調用它的函數(shù)虑椎,拋出異常,把控制權交給 Web 服務器俱笛。

flask 的組件

被設計為可擴展形式捆姜,只自帶兩個核心組件:

  • werkzeug,負責處理 路由迎膜、調試泥技、WSGI
  • jinja2,模板引擎磕仅,負責對模板進行渲染

其他組件需要單獨安裝珊豹、初始化

擴展的來源:

  • 社區(qū)開發(fā)
  • py 標準庫/包
  • 自行開發(fā)

使用:

pip install flask-mail # pip 安裝

from flask.ext.mail import Mail # 導入, 專為 Flask 開發(fā)的擴展簸呈,都在 flask.ext 命名空間下, virtualenv 環(huán)境中,目錄為lib/python2.7/site-packages/

mail = Mail(app) # 初始化店茶,將 程序實例(app) 作為參數(shù)傳給 擴展的構造函數(shù)蜕便,進行初始化。通常在創(chuàng)建程序實例時進行贩幻。

mail.send(msg) # 使用

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末轿腺,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子丛楚,更是在濱河造成了極大的恐慌族壳,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件趣些,死亡現(xiàn)場離奇詭異仿荆,居然都是意外死亡,警方通過查閱死者的電腦和手機坏平,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門赖歌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人功茴,你說我怎么就攤上這事庐冯。” “怎么了坎穿?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵展父,是天一觀的道長。 經(jīng)常有香客問我玲昧,道長栖茉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任孵延,我火速辦了婚禮吕漂,結果婚禮上,老公的妹妹穿的比我還像新娘尘应。我一直安慰自己惶凝,他們只是感情好,可當我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布犬钢。 她就那樣靜靜地躺著苍鲜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪玷犹。 梳的紋絲不亂的頭發(fā)上混滔,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天,我揣著相機與錄音,去河邊找鬼坯屿。 笑死油湖,一個胖子當著我的面吹牛,可吹牛的內容都是我干的领跛。 我是一名探鬼主播肺魁,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼隔节!你這毒婦竟也來了鹅经?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤怎诫,失蹤者是張志新(化名)和其女友劉穎瘾晃,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體幻妓,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡蹦误,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了肉津。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片强胰。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖妹沙,靈堂內的尸體忽然破棺而出偶洋,到底是詐尸還是另有隱情,我是刑警寧澤距糖,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布玄窝,位于F島的核電站,受9級特大地震影響悍引,放射性物質發(fā)生泄漏恩脂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一趣斤、第九天 我趴在偏房一處隱蔽的房頂上張望俩块。 院中可真熱鬧,春花似錦浓领、人聲如沸玉凯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽壮啊。三九已至嫉鲸,卻和暖如春撑蒜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工座菠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留狸眼,地道東北人。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓浴滴,卻偏偏與公主長得像拓萌,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子升略,可洞房花燭夜當晚...
    茶點故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內容

  • 22年12月更新:個人網(wǎng)站關停微王,如果仍舊對舊教程有興趣參考 Github 的markdown內容[https://...
    tangyefei閱讀 35,180評論 22 257
  • [TOC]一直想做源碼閱讀這件事,總感覺難度太高時間太少品嚣,可望不可見炕倘。最近正好時間充裕,決定試試做一下翰撑,并記錄一下...
    何柯君閱讀 7,184評論 3 98
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理罩旋,服務發(fā)現(xiàn),斷路器眶诈,智...
    卡卡羅2017閱讀 134,651評論 18 139
  • 這幾天想學新東西涨醋,就看了flask框架,本身對python不太了解逝撬,網(wǎng)上的很多教程看了浴骂,總是在某些地方卡住。翻到一...
    易木成華閱讀 2,232評論 0 11
  • 快速啟動 是不是很渴望馬上開始跋艹薄靠闭?這篇文檔將會很好的向你介紹Flask。假設你已經(jīng)安裝好了Flask坎炼。如果還沒有安...
    催眠_a363閱讀 681評論 0 1