摘要:有兩類應(yīng)用級和請求級。一個響應(yīng)中非常重要的部分是狀態(tài)碼,默認(rèn)設(shè)置來指示請求已經(jīng)成功處理。重定向通常由響應(yīng)狀態(tài)碼注明并且重定向的由頭部的給出。因為這些變化,應(yīng)用程序獲得一組基本的命令行選項。運行顯示可用信息在應(yīng)用程序上下文的內(nèi)部運行一個。
5、請求-響應(yīng)循環(huán)
現(xiàn)在你已經(jīng)玩過一個基本的Flask應(yīng)用程序,你也許想要知道更多關(guān)于Flask如何施展魔力。下面章節(jié)描述了一些框架設(shè)計方面的特點。
當(dāng)Flask從客戶端收到一個請求,它需要提供幾個可用對象給視圖函數(shù)處理。request對象是個不錯的例子,它封裝了客戶端發(fā)送的HTTP請求。
Flask視圖函數(shù)訪問request對象的最好方式,就是作為一個參數(shù)發(fā)送它,但這需要每個單一視圖函數(shù)在應(yīng)用程序中有一個額外的參數(shù)。考慮一下,如果request對象不是唯一一個視圖函數(shù)需要訪問完成請求的對象,事情將會變得更加復(fù)雜。
為了避免弄亂視圖函數(shù)那些可能需要或不需要的參數(shù),F(xiàn)lask使用context來臨時確定可訪問的全局對象。也多虧了context,視圖函數(shù)可以寫成下面這樣:
from flask import request @app.route("/") def index(): user_agent = request.headers.get("User-Agent") return "Your browser is %s
" % user_agent
注意,在這個視圖函數(shù)中,request是如何被作為一個全局變量來使用的。現(xiàn)實中,request是不能作為全局變量的,如果是多線程服務(wù)器,同一時間線程作用于不同客戶端的不同請求,所以每一個線程需要看到request中的不同對象。contexts使得Flask確定可訪問的全局變量而不干擾其他線程。
注:線程是可以獨立管理的最小指令序列。一個進程中有多個活動的線程是非常常見的,有時分享內(nèi)存或文件句柄資源。多線程web服務(wù)器會啟動一個線程池并從池中選擇一個線程來處理每個傳入的請求。
Flask有兩類context:應(yīng)用級context 和 請求級context。表2-1展示了這些context提供的變量。
表2-1. Flask全局context
Flask激活(或壓棧)應(yīng)用級context和請求級context在調(diào)度請求之前,然后刪除他們當(dāng)請求被處理后。當(dāng)應(yīng)用程序context被壓入棧,線程中current_app和g變量變得可用;同樣的,當(dāng)請求級context被壓入棧,request和session變量也同樣變得可用。如果這些變量中的任何一個不是由激活的應(yīng)用級或請求級context訪問,會產(chǎn)生錯誤。在后面的章節(jié)會詳細(xì)討論四個context變量,所以不要擔(dān)心你不理解它們的用處。
下面的Python shell會話演示了應(yīng)用級context是如何工作的:
>>> from hello import app >>> from flask import current_app >>> current_app.name Traceback (most recent call last): ... RuntimeError: working outside of the application context >>> app_ctx = app.app_context() >>> app_ctx.push() >>> current_app.name "hello" >>> app_ctx.pop()
在這個示例中,當(dāng)應(yīng)用級context沒有激活,但是卻作為有效的context被壓入棧中,current_app.name報錯。注意在應(yīng)用程序?qū)嵗幸粋€應(yīng)用級context是如何通過調(diào)用app.app_context()來獲得的。
當(dāng)一個應(yīng)用程序收到客戶端的請求,它需要找到響應(yīng)的視圖函數(shù)為之服務(wù)。對于這個任務(wù),F(xiàn)lask會在應(yīng)用程序的URL映射中查找請求的URL,該映射包含URLs和操作它們的視圖函數(shù)。Flask通過app.route裝飾器或非裝飾器版本app.add_url_rule()來建立這個映射。
看一下Flask應(yīng)用程序中URL映射是怎樣的,你可以在Python shell中檢查hello.py創(chuàng)建的映射。測試中,請確保你的虛擬環(huán)境是激活狀態(tài):
(venv) % python >>> from hello import app >>> app.url_map Map([index>, " (HEAD, OPTIONS, GET) -> static>, " (HEAD, OPTIONS, GET) -> user>])
/和/user/
URL映射中所示的HEAD、OPTIONS、GET元素為request方法,由路由處理。Flask連接方法到每個路由,這樣不同的請求方法發(fā)送到相同的URL可以被不同的視圖函數(shù)處理。HEAD和OPTIONS方法由Flask自動管理,所以實際上可以說,在這個應(yīng)用程序中URL映射的三個路由都連接到GET方法了。在第四章你將學(xué)習(xí)為路由指定不同的請求方法。
有些時候在每個請求處理之前或之后執(zhí)行代碼是非常有用的。例如,在開始每一個請求前可能有必要創(chuàng)建數(shù)據(jù)庫連接,或?qū)τ脩粽埱筮M行驗證。為了避免復(fù)制處理這些操作的代碼到每一個視圖函數(shù)中,F(xiàn)lask給你選擇注冊相同函數(shù)來調(diào)用,在請求被分配給視圖函數(shù)之前或之后。
請求hooks由裝飾器實現(xiàn)。下面是四個Flask支持的hooks:
before_first_request:在第一個請求被處理前注冊一個函數(shù)運行。
before_request:在每一個請求前注冊一個函數(shù)運行。
after_request:如果沒有未處理的異常發(fā)生,在每一個請求后注冊一個函數(shù)運行。
teardown_request:即使未處理的異常發(fā)生,在每一個請求后注冊一個函數(shù)運行。
在請求hook函數(shù)和視圖函數(shù)之間共享數(shù)據(jù)的慣用方法就是使用g全局context。例如,before_request處理程序可以從數(shù)據(jù)庫加載已登錄的用戶并保存在g.user中。之后,當(dāng)視圖函數(shù)被調(diào)用,可以從那訪問用戶。
請求hooks的示例會在未來的章節(jié)中展示給大家,所以不用擔(dān)心,
當(dāng)Flask調(diào)用一個視圖函數(shù),并期望它的返回值去響應(yīng)該請求。大多數(shù)的響應(yīng)是將簡單字符串構(gòu)成的HTML頁面發(fā)回給客戶端。
但是HTTP協(xié)議需要比字符串更多的信息作為請求的響應(yīng)。一個HTTP響應(yīng)中非常重要的部分是狀態(tài)碼,F(xiàn)lask默認(rèn)設(shè)置200來指示請求已經(jīng)成功處理。
當(dāng)視圖函數(shù)需要用不同的狀態(tài)碼響應(yīng),可以在響應(yīng)文本后添加數(shù)字碼作為第二個返回值。例如,下面的視圖函數(shù)返回400錯誤狀態(tài)碼的請求:
@app.route("/") def index(): return "Bad Request
", 400
視圖函數(shù)返回的響應(yīng)還可以攜帶第三個參數(shù),添加一個頭部字典給HTTP響應(yīng)。通常很少用到,但是你可以在第十四章看到示例。
除了返回一個、兩個或三個值的元組,F(xiàn)lask視圖函數(shù)可以選擇返回response對象。make_response()函數(shù)可攜帶一個、兩個或三個參數(shù),和視圖函數(shù)返回的值一樣,并返回一個response對象。有時候在視圖函數(shù)中執(zhí)行這個轉(zhuǎn)換是非常有用的,然后使用response對象中的方法進一步配置響應(yīng)。下面的示例創(chuàng)建response對象并設(shè)置cookie:
from flask import make_response @app.route("/") def index(): response = make_response("This document carries a cookie!
") response.set_cookie("answer", "42") return response
有一類特殊的響應(yīng)稱作重定向。這類響應(yīng)不包含頁面文檔;只是給瀏覽器一個新的URL去加載新的頁面。重定向通常和web表單一起使用,你將在第四章學(xué)習(xí)。
重定向通常由302響應(yīng)狀態(tài)碼注明并且重定向的URL由頭部的Location給出。重定向響應(yīng)可以使用三個值的返回生成,也可通過響應(yīng)對象生成,但是鑒于它頻繁的使用,F(xiàn)lask提供redirect()函數(shù)來創(chuàng)建這樣的響應(yīng):
from flask import redirect @app.route("/") def index(): return redirect("http://www.example.com")
另一個具有中斷功能的特殊響應(yīng)用來錯誤處理。下面的示例,當(dāng)URL給出的id動態(tài)參數(shù)不是一個合法的用戶時返回狀態(tài)碼404:
from flask import abort @app.route("/user/") def get_user(id): user = load_user(id) if not user: abort(404) return " Hello, %s
" % user.name
注意終止不是指將控制權(quán)返回給調(diào)用它的函數(shù),而是指通過拋出異常將控制權(quán)返回給web服務(wù)。
6、Flask擴展Flask是可擴展的。它故意騰出地給重要的功能,例如數(shù)據(jù)庫和用戶授權(quán),給你自由去選擇最適合你的應(yīng)用程序的包,或?qū)懸粋€自己想要的。
社區(qū)開發(fā)了非常多的擴展用于各種用途,如果這還不夠,可以使用任何Python標(biāo)準(zhǔn)包和庫。為了讓你了解一個擴展是如何并入一個應(yīng)用程序的,下面的章節(jié)給hello.py添加一個擴展,增加應(yīng)用程序的命令行參數(shù)。
Flask開發(fā),其web服務(wù)器支持一系列的啟動配置選項,但是配置它們的唯一方式只有在腳本中傳遞參數(shù)給app.run()并調(diào)用。這不是非常的方便,理想方法是通過命令行參數(shù)傳遞配置選項。
Flask-Script是給你的Flask應(yīng)用程序添加命令行解釋的擴展。它打包了一組通用的選項,還支持自定義命令。
使用pip安裝擴展:
(venv) $ pip install flask-script
示例2-3展示了在 hello.py 應(yīng)用程序中添加命令行解釋的變化。
示例2-3. hello.py:使用Flask-Script
from flask.ext.script import Manager manager = Manager(app) # ... if __name__ == "__main__": manager.run()
專為Flask開發(fā)的擴展暴露在flask.ext命名空間下。Flask-Script從flask.ext.script中導(dǎo)出一個名為Manager的類。
初始化這個擴展的方法和其他許多擴展一樣:主類實例的初始化是通過將應(yīng)用程序?qū)嵗鳛閰?shù)傳遞給構(gòu)造函數(shù)實現(xiàn)的。創(chuàng)建的對象適當(dāng)?shù)挠糜诿恳粋€擴展。在這個示例中,服務(wù)器啟動通過manager.run()來路由,且命令行在這被解析。
建議:如果你有克隆在GitHub上的應(yīng)用程序,你現(xiàn)在可以運行git checkout 2c來切換到這個版本的應(yīng)用程序。
因為這些變化,應(yīng)用程序獲得一組基本的命令行選項。運行hello.py顯示可用信息:
$ python hello.py usage: hello.py [-h] {shell, runserver} ... positional arguments: {shell, runserver} shell 在Flask應(yīng)用程序上下文的內(nèi)部運行一個Python Shell。 runserver 運行Flask開發(fā)服務(wù)器,例如:app.run() optional arguments: -h, --help 顯示這個幫助信息并退出
shell命令用于在應(yīng)用程序上下文中啟動一個Python shell會話。你可以使用這個會話去運行維護任務(wù),或測試,或調(diào)試錯誤。
runserver命令,就像它的名稱一樣,啟動web服務(wù)。運行python hello.py runserver在調(diào)試模式下啟動web服務(wù),還有更多的選項:
(venv) $ python hello.py runserver --help usage: hello.py runserver [-h] [-t HOST] [-p PORT] [--threaded] [--processes PROCESSES] [--passthrough-errors] [-d] [-r] 運行Flask開發(fā)服務(wù)器,例如:app.run() optional arguments: -h, --help 顯示這個幫助信息并退出 -t HOST, --host HOST -p PORT, --port PORT --threaded --processes PROCESSES --passthrough-errors -d, --no-debug -r, --no-reload
--host參數(shù)是一個非常有用的選項,因為它能告訴web服務(wù)器監(jiān)聽哪個網(wǎng)絡(luò)接口的客戶端連接。默認(rèn),F(xiàn)lask開發(fā)的web服務(wù)器監(jiān)聽localhost的連接,所以只有來自內(nèi)部計算機運行的服務(wù)器可以接收。下面的命令使得web服務(wù)器監(jiān)聽公網(wǎng)接口,其他網(wǎng)絡(luò)上的計算機可以連接:
(venv) $ python hello.py runserver --host 0.0.0.0 * Running on http://0.0.0.0:5000/ * Restarting with reload
現(xiàn)在web服務(wù)器應(yīng)該可以從網(wǎng)絡(luò)中的任何一臺計算機訪問 http://a.b.c.d:5000 ,“a.b.c.d”是運行服務(wù)的計算機的外部IP地址。
這一章介紹了請求響應(yīng)的概念,但說的更多的是響應(yīng)。Flask使用模板為生成響應(yīng)提供非常好的支持,這是非常重要的話題,下一章會重點講它。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/37441.html
摘要:注對于開發(fā)者來說,傳給應(yīng)用程序構(gòu)造函數(shù)的參數(shù)是比較容易弄混淆的。在應(yīng)程序中定義路由的最便捷的方式是通過顯示定義在應(yīng)用程序?qū)嵗系难b飾器,注冊被裝飾的函數(shù)來作為一個路由。一個常見的模式是使用裝飾器來注冊函數(shù)作為一個事件處理程序。 在這一章,你將學(xué)習(xí)Flask應(yīng)用程序不同部分。同時你將編寫和運行你的第一個Flask web應(yīng)用程序。 1、初始化 在這章,你將學(xué)到Flask應(yīng)用程序的不...
摘要:被定義在包的構(gòu)造函數(shù)中的應(yīng)用程序工廠函數(shù)會在示例中展示。這個構(gòu)造函數(shù)導(dǎo)入大部分當(dāng)前需要使用的擴展,但因為沒有應(yīng)用程序?qū)嵗跏蓟鼈儯梢员粍?chuàng)建但不初始化通過不傳遞參數(shù)給它們的構(gòu)造函數(shù)。而應(yīng)用程序范圍內(nèi)的錯誤處理則必須使用。 雖然小型web應(yīng)用程序用單個腳本可以很方便,但這種方法卻不能很好地擴展。隨著應(yīng)用變得復(fù)雜,在單個大的源文件中處理會變得問題重重。 與大多數(shù)其他web框架不同,F(xiàn)l...
摘要:單元測試這個應(yīng)用非常小以至于不需要太多的測試,但是作為示例會在示例中展示兩個簡單的測試定義。示例單元測試編寫好的測試使用的是來自于標(biāo)準(zhǔn)庫中標(biāo)準(zhǔn)的包。為了運行單元測試,可以在腳本中增加一個自定義的命令。 4、啟動腳本 頂層目錄中的manage.py文件用于啟動應(yīng)用。這個腳本會在示例7-8中展示。 示例7-8. manage.py:啟動腳本 #!/usr/bin/env python im...
摘要:示例使用的模板的指令通過從引用來實現(xiàn)模板的繼承。上面的模板定義了三個,分別命名為和。同時返回相應(yīng)錯誤的數(shù)字狀態(tài)碼。示例帶有導(dǎo)航欄的基礎(chǔ)應(yīng)用程序模板這個模板中的塊中只是一個名為的元素,它包含了在派生模板中定義的名為的空。 2、集成Twitter Bootstrap的Flask-Bootstrap Bootstrap是Twitter的一個開源框架,提供用戶交互組件來創(chuàng)建一個清新且有吸引力...
摘要:用真實的值替換變量并返回最終響應(yīng)字符串,這個過程稱為渲染。示例展示模板實現(xiàn)該響應(yīng)。控制結(jié)構(gòu)提供一些控制結(jié)構(gòu)用于改變模板流。這個示例展示如何使用循環(huán)做到這些同樣支持宏,這和代碼中的函數(shù)很像。 寫代碼最關(guān)鍵的是要易于維護且結(jié)構(gòu)清晰整潔。目前為止,你看到的例子都過于簡單從而沒有做這方面的要求。Flask視圖函數(shù)希望將兩個應(yīng)該完全獨立的任務(wù)一并處理,兩個任務(wù)有兩種代碼,一并處理勢必會引發(fā)問題。...
閱讀 3016·2021-10-08 10:18
閱讀 732·2019-08-30 15:54
閱讀 1067·2019-08-29 18:43
閱讀 2441·2019-08-29 15:33
閱讀 1305·2019-08-29 15:29
閱讀 1604·2019-08-29 13:29
閱讀 1026·2019-08-26 13:46
閱讀 1702·2019-08-26 11:55