W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
對于 Web 應(yīng)用,與客戶端發(fā)送給服務(wù)器的數(shù)據(jù)交互至關(guān)重要。在 Flask 中 由全局的 request 對象來提供這些信息。如果你有一定的 Python 經(jīng)驗,你會好奇,為什么這個對象是全局的,為什么 Flask 還能保證 線程安全。答案是環(huán)境作用域:
內(nèi)幕
如果你想理解其工作機制及如何利用環(huán)境局部變量實現(xiàn)自動化測試,請閱 讀此節(jié),否則可跳過。
Flask 中的某些對象是全局對象,但卻不是通常的那種。這些對象實際上是特定 環(huán)境的局部對象的代理。雖然很拗口,但實際上很容易理解。
想象一下處理線程的環(huán)境。一個請求傳入,Web 服務(wù)器決定生成一個新線程( 或者別的什么東西,只要這個底層的對象可以勝任并發(fā)系統(tǒng),而不僅僅是線程)。 當(dāng) Flask 開始它內(nèi)部的請求處理時,它認定當(dāng)前線程是活動的環(huán)境,并綁定當(dāng) 前的應(yīng)用和 WSGI 環(huán)境到那個環(huán)境上(線程)。它的實現(xiàn)很巧妙,能保證一個應(yīng) 用調(diào)用另一個應(yīng)用時不會出現(xiàn)問題。
所以,這對你來說意味著什么?除非你要做類似單元測試的東西,否則你基本上 可以完全無視它。你會發(fā)現(xiàn)依賴于一段請求對象的代碼,因沒有請求對象無法正 常運行。解決方案是,自行創(chuàng)建一個請求對象并且把它綁定到環(huán)境中。單元測試 的最簡單的解決方案是:用 test_request_context() 環(huán) 境管理器。結(jié)合 with 聲明,綁定一個測試請求,這樣你才能與之交互。下面 是一個例子:
from flask import request
with app.test_request_context('/hello', method='POST'):
# now you can do something with the request until the
# end of the with block, such as basic assertions:
assert request.path == '/hello'
assert request.method == 'POST'
另一種可能是:傳遞整個 WSGI 環(huán)境給 request_context() 方法:
from flask import request
with app.request_context(environ):
assert request.method == 'POST'
API 章節(jié)對請求對象作了詳盡闡述(參見 request ),因此這 里不會贅述。此處寬泛介紹一些最常用的操作。首先從 flask 模塊里導(dǎo)入它:
from flask import request
當(dāng)前請求的 HTTP 方法可通過 method 屬性來訪問。通 過:attr:~flask.request.form 屬性來訪問表單數(shù)據(jù)( POST 或 PUT 請求 提交的數(shù)據(jù))。這里有一個用到上面提到的那兩個屬性的完整實例:
@app.route('/login', methods=['POST', 'GET'])
def login():
error = None
if request.method == 'POST':
if valid_login(request.form['username'],
request.form['password']):
return log_the_user_in(request.form['username'])
else:
error = 'Invalid username/password'
# the code below is executed if the request method
# was GET or the credentials were invalid
return render_template('login.html', error=error)
當(dāng)訪問 form 屬性中的不存在的鍵會發(fā)生什么?會拋出一個特殊的 KeyError 異常。你可以像捕獲標準的 KeyError 一樣來捕獲它。 如果你不這么做,它會顯示一個 HTTP 400 Bad Request 錯誤頁面。所以,多數(shù) 情況下你并不需要干預(yù)這個行為。
你可以通過 args 屬性來訪問 URL 中提交的參數(shù) ( ?key=value ):
searchword = request.args.get('q', '')
我們推薦用 get 來訪問 URL 參數(shù)或捕獲 KeyError ,因為用戶可能會修 改 URL,向他們展現(xiàn)一個 400 bad request 頁面會影響用戶體驗。
欲獲取請求對象的完整方法和屬性清單,請參閱 request 的 文檔。
用 Flask 處理文件上傳很簡單。只要確保你沒忘記在 HTML 表單中設(shè)置 enctype="multipart/form-data" 屬性,不然你的瀏覽器根本不會發(fā)送文件。
已上傳的文件存儲在內(nèi)存或是文件系統(tǒng)中一個臨時的位置。你可以通過請求對象 的 files 屬性訪問它們。每個上傳的文件都會存儲在 這個字典里。它表現(xiàn)近乎為一個標準的 Python file 對象,但它還有 一個 save() 方法,這個方法 允許你把文件保存到服務(wù)器的文件系統(tǒng)上。這里是一個用它保存文件的例子:
from flask import request
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['the_file']
f.save('/var/www/uploads/uploaded_file.txt')
...
如果你想知道上傳前文件在客戶端的文件名是什么,你可以訪問 filename 屬性。但請記住, 永遠不要信任這個值,這個值是可以偽造的。如果你要把文件按客戶端提供的 文件名存儲在服務(wù)器上,那么請把它傳遞給 Werkzeug 提供的 secure_filename() 函數(shù):
from flask import request
from werkzeug import secure_filename
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['the_file']
f.save('/var/www/uploads/' + secure_filename(f.filename))
...
一些更好的例子,見 上傳文件 模式。
你可以通過 cookies 屬性來訪問 Cookies,用 響應(yīng)對象的 set_cookie 方法來設(shè)置 Cookies。請 求對象的 cookies 屬性是一個內(nèi)容為客戶端提交的 所有 Cookies 的字典。如果你想使用會話,請不要直接使用 Cookies,請參 考 會話 一節(jié)。在 Flask 中,已經(jīng)注意處理了一些 Cookies 安全 細節(jié)。
讀取 cookies:
from flask import request
@app.route('/')
def index():
username = request.cookies.get('username')
# use cookies.get(key) instead of cookies[key] to not get a
# KeyError if the cookie is missing.
存儲 cookies:
from flask import make_response
@app.route('/')
def index():
resp = make_response(render_template(...))
resp.set_cookie('username', 'the username')
return resp
可注意到的是,Cookies 是設(shè)置在響應(yīng)對象上的。由于通常視圖函數(shù)只是返 回字符串,之后 Flask 將字符串轉(zhuǎn)換為響應(yīng)對象。如果你要顯式地轉(zhuǎn)換,你 可以使用 make_response() 函數(shù)然后再進行修改。
有時候你想設(shè)置 Cookie,但響應(yīng)對象不能醋在。這可以利用 延遲請求回調(diào) 模式實現(xiàn)。
為此,也可以閱讀 關(guān)于響應(yīng) 。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: