Flask(7)- request 物件
Flask 中很重要的 request 物件
- 瀏覽器訪問服務端時,向服務端傳送請求
- Flask 程式使用 request 物件描述請求資訊
- 當你想獲取請求體、請求引數、請求頭資料的時候,就需要靠 request 物件了
- 這一篇會用結果驅動原始碼解析的方式來講解
真實使用場景
瀏覽器訪問服務端,需要將相應的資料傳送給服務端,可能有如下場景:
- 通過 URL 引數進行查詢,瀏覽器需要將查詢引數傳送給服務端
- 提交表單 form 進行查詢,瀏覽器需要將表單 form 中的欄位傳送給服務端
- 上傳檔案,瀏覽器需要將檔案傳送給服務端
- 通過 JSON 格式的請求體進行請求,一般是 post 請求
服務端收到將客戶端傳送的資料後,封裝形成一個請求物件,在 Flask 中,請求物件是一個模組變數 flask.request
request 包含的常用屬性
屬性 | 說明 |
---|---|
method | 當前的請求方法 |
form | 表單引數及其值的字典物件 |
args | 查詢字串的字典物件 |
values | 包含所有資料的字典物件 |
json | 如果 mimetype 是 application/json,這個引數將會解析 json 資料,如果不是則返回 None |
headers | http 協議 請求頭 |
cookies | cookie 名稱和值的字典物件 |
files | 與上傳檔案有關的資料 |
form、args、values、json 都是獲取 http 請求的請求資料的屬性,只不過請求體型別不同
還記得之前講 url 組成的時候,request 物件也能獲取 url 相關引數嗎,複習下
request 獲取 url 組成的常用屬性
假設 URL 等於http://localhost/query?userId=123,request物件中與 URL 引數相關的屬性如下
屬性 | 說明 |
---|---|
url | http://localhost/query?userId=123 |
base_url | http://localhost/query |
host | localhost |
host_url | http://localhost/ |
path | /query |
full_path | /query?userId=123 |
獲取 url 請求引數的栗子
程式碼
#!usr/bin/env python # -*- coding:utf-8 _*-""" # author: 小菠蘿測試筆記 # blog: https://www.cnblogs.com/poloyy/ # time: 2021/7/11 11:13 上午 # file: 5_request.py """ from flask import Flask, request app = Flask(__name__) @app.route('/query') def query(): return {"name": request.args['name'], "age": request.args['age']} @app.route('/query2') def query2(): print('args =', request.args) print('form =', request.form) return "form" @app.route('/query3') def query3(): print('args =', request.args) print('json =', request.json) return "json" @app.route('/query4') def query4(): return {"name": request.values['name'], "age": request.values['age']} if __name__ == '__main__': app.run(debug=True)
- 下面我會用 postman 統一通過 params,就是 url 請求引數傳資料
- 在 Flask 裡面,把四種獲取請求資料的屬性都寫一遍,然後看看最後的結果,提前幫大家踩坑
postman 發起請求的結果
/query
/query2
控制檯輸出
args = ImmutableMultiDict([('name', 'zhangsan'), ('age', '13')]) form = ImmutableMultiDict([])
用 form 屬性的話得到是一個空字典哦
/query3
控制檯輸出
args = ImmutableMultiDict([('name', 'zhangsan'), ('age', '13')]) json = None
用 json 屬性的話得到是一個 None 哦,所以無論如何都不要用 json 獲取 url 請求引數喲!
/query4
可以看到 values 屬性也能拿到 url 請求引數哦
獲取表單引數的栗子
程式碼
#!usr/bin/env python # -*- coding:utf-8 _*- """ # author: 小菠蘿測試筆記 # blog: https://www.cnblogs.com/poloyy/ # time: 2021/7/11 1:47 下午 # file: 5_request_form.py """ from flask import Flask, request app = Flask(__name__) @app.route('/addUser', methods=['POST']) def check_login(): return {"name": request.form['name'], "age": request.form['age']} @app.route('/addUser2', methods=['POST']) def check_login2(): print('form =', request.form) print('args =', request.args) return "good" @app.route('/addUser3', methods=['POST']) def check_login3(): print('form =', request.form) print('json =', request.json) return "good" @app.route('/addUser4', methods=['POST']) def check_login4(): return {"name": request.values['name'], "age": request.values['age']} if __name__ == '__main__': app.run(debug=True)
- 下面我會用 postman 統一通過 form-data,就是表單格式來傳資料
- 在 Flask 裡面,把四種獲取請求資料的屬性都寫一遍,然後看看最後的結果,提前幫大家踩坑
postman 發起請求的結果
/addUser
/addUser2
控制檯輸出
form = ImmutableMultiDict([('name', 'poloyy'), ('age', '12')]) args = ImmutableMultiDict([])
用 args 屬性的話得到是一個空字典哦
/addUser3
控制檯輸出
form = ImmutableMultiDict([('name', 'poloyy'), ('age', '12')]) json = None
用 json 屬性的話得到是一個 None 哦,所以無論如何都不要用 json 獲取 form-data 喲!
/addUser4
可以看到 values 屬性也能拿到 form 表單提交的資料哦
獲取 Json 資料的栗子
程式碼
#!usr/bin/env python # -*- coding:utf-8 _*- """ # author: 小菠蘿測試筆記 # blog: https://www.cnblogs.com/poloyy/ # time: 2021/7/11 1:47 下午 # file: 5_request_form.py """ from flask import Flask, request app = Flask(__name__) @app.route('/addJson', methods=['POST']) def check_login(): return {"name": request.json['name'], "age": request.json['age']} @app.route('/addJson2', methods=['POST']) def check_login2(): print('json =', request.json) print('args =', request.args) return "good" @app.route('/addJson3', methods=['POST']) def check_login3(): print('json =', request.json) print('form =', request.form) return "good" @app.route('/addJson4', methods=['POST']) def check_login4(): print('json =', request.json, type(request.json)) print('values =', request.values) return {"name": request.json['name'], "age": request.json['age']}
if __name__ == '__main__': app.run(debug=True)
- 下面我會用 postman 統一通過 raw-json,就是 Json 格式的請求體來傳資料
- 在 Flask 裡面,把四種獲取請求資料的屬性都寫一遍,然後看看最後的結果,提前幫大家踩坑
postman 發起請求的結果
/addJson
/addJson2
json = {'age': '12', 'name': 'poloyy'} args = ImmutableMultiDict([])
用 args 屬性的話得到是一個空字典哦
/addJson3
json = {'age': '12', 'name': 'poloyy'} form = ImmutableMultiDict([])
用 form 屬性的話得到是一個空字典哦
/addJson4
這裡要注意的是,當你的請求體是 Json 時,是不能通過 values 來獲取請求資料哦!!
最後來看看 request.json 會返回什麼吧
json = {'age': '12', 'name': 'poloyy'} <class 'dict'>
request.json 拿到的就是 Json 格式的請求體,並且自動轉換成字典了哦!
為什麼 requests.values 能獲取 form、args 的資料,但是拿不到 json 的資料呢?
request.values 原始碼
- 能看到,它本質就是獲取 args、form 的資料,但不包含 json 資料
- 但是這裡有個重點,只有你的請求方法不為 GET 的時候,傳送 form 表單資料才能通過 request.values 拿到請求資料
- 來試試是不是真的這樣
程式碼
@app.route('/query4', methods=["GET", "POST"]) def query4(): print(request.form) print(request.args) print(request.values) return {"name": request.values['name'], "age": request.values['age']}
postman 發起 GET 請求,form-data 傳資料
直接報錯,找不到對應的 name key,因為 request.values 是空的
控制檯輸出
ImmutableMultiDict([('name', 'poloyy'), ('age', '12')]) CombinedMultiDict([ImmutableMultiDict([])]) ImmutableMultiDict([])
很明顯,request.form 是能拿到資料的,但是 request.value 是拿不到資料哦
postman 發起 POST 請求,form-data 傳資料
這次就能正常顯示返回值啦
控制檯輸出
ImmutableMultiDict([('name', 'poloyy'), ('age', '12')]) ImmutableMultiDict([]) CombinedMultiDict([ImmutableMultiDict([]), ImmutableMultiDict([('name', 'poloyy'), ('age', '12')])])
看原始碼應該知道,當非 GET 請求的時候傳遞表單資料,request.values 也能獲取得到 request.form 的資料