Flask請(qǐng)求數(shù)據(jù)獲取方法詳解
一、工作原理
在 Flask 中,所有客戶端請(qǐng)求的數(shù)據(jù)都通過全局的 request 對(duì)象訪問。該對(duì)象是 請(qǐng)求上下文 的一部分,僅在請(qǐng)求處理期間存在。Flask 在收到請(qǐng)求時(shí)自動(dòng)創(chuàng)建 request 對(duì)象,并根據(jù)請(qǐng)求類型(如 GET、POST)和內(nèi)容類型(如表單、JSON)解析數(shù)據(jù),將不同來源的數(shù)據(jù)封裝到對(duì)應(yīng)的屬性中(如 args、form、json)。
二、常用方法
查詢參數(shù)(URL參數(shù))
使用 request.args
(類型:ImmutableMultiDict
)獲取 URL 中的查詢參數(shù)。
name = request.args.get('name') # 獲取單個(gè)參數(shù) all_args = request.args.to_dict() # 轉(zhuǎn)為字典
表單數(shù)據(jù)
針對(duì) application/x-www-form-urlencoded
或 multipart/form-data
類型的 POST 請(qǐng)求,使用 request.form
。
username = request.form.get('username')
JSON 數(shù)據(jù)
當(dāng)請(qǐng)求的 Content-Type
為 application/json
時(shí),使用 request.json
直接獲取解析后的字典。
data = request.json
文件上傳
通過 request.files
獲取上傳的文件(類型:FileStorage
)。
file = request.files.get('file') if file: file.save('uploaded_file.txt')
原始數(shù)據(jù)
使用request.data
獲取未經(jīng)處理的原始字節(jié)數(shù)據(jù)(如非表單、非JSON的請(qǐng)求體)。請(qǐng)求頭與Cookies
user_agent = request.headers.get('User-Agent') user_token = request.cookies.get('token')
三、高級(jí)用法
處理多值參數(shù)
當(dāng)參數(shù)有多個(gè)值時(shí)(如多選框),使用getlist
:
selected_ids = request.form.getlist('ids')
- 強(qiáng)制解析JSON
即使Content-Type
不是application/json
,也可強(qiáng)制解析:
data = request.get_json(force=True)
- 流式處理大文件
使用request.stream
逐塊讀取數(shù)據(jù),避免內(nèi)存溢出:
@app.route('/upload', methods=['POST']) def upload(): def generate(): chunk_size = 4096 while True: chunk = request.stream.read(chunk_size) if not chunk: break # 處理chunk... return 'Upload complete'
混合數(shù)據(jù)(表單+JSON)使用
request.values
合并查詢參數(shù)和表單數(shù)據(jù)(不推薦混用,需謹(jǐn)慎處理邏輯)。
四、完整示例
from flask import Flask, request, jsonify app = Flask(__name__) @app.route('/api', methods=['GET', 'POST']) def handle_request(): # 獲取查詢參數(shù) query_param = request.args.get('q') # 根據(jù)不同請(qǐng)求類型處理數(shù)據(jù) if request.method == 'POST': # 處理表單數(shù)據(jù) username = request.form.get('username') # 處理JSON數(shù)據(jù) json_data = request.get_json(silent=True) # 解析失敗返回None # 處理文件上傳 uploaded_file = request.files.get('file') if uploaded_file: uploaded_file.save('uploads/' + uploaded_file.filename) return jsonify({ "query_param": query_param, "username": username, "json_data": json_data, "file_uploaded": bool(uploaded_file) }) else: return jsonify({"query_param": query_param}) if __name__ == '__main__': app.run(debug=True)
五、注意事項(xiàng)
請(qǐng)求方法影響數(shù)據(jù)獲取
- GET 請(qǐng)求只有
args
,無form
或files
。 - POST 需根據(jù)
Content-Type
選擇正確的屬性(如form
或json
)。
- GET 請(qǐng)求只有
處理缺失數(shù)據(jù)
使用.get('key')
而非['key']
避免KeyError
,可指定默認(rèn)值:
value = request.form.get('key', 'default')
JSON解析安全
- 使用
request.get_json(silent=True)
避免解析失敗拋出異常。 - 使用
force=True
時(shí)需注意客戶端可能發(fā)送非法數(shù)據(jù)。
- 使用
文件上傳安全
- 限制文件類型和大?。ㄍㄟ^
MAX_CONTENT_LENGTH
配置)。 - 驗(yàn)證文件名,避免路徑遍歷漏洞。
- 限制文件類型和大?。ㄍㄟ^
六、擴(kuò)展知識(shí)
請(qǐng)求鉤子預(yù)處理
使用@app.before_request
在請(qǐng)求處理前統(tǒng)一驗(yàn)證或預(yù)處理數(shù)據(jù):
@app.before_request def check_auth(): if not request.endpoint == 'login' and not validate_token(request.headers.get('Token')): return jsonify({"error": "Unauthorized"}), 401
第三方庫擴(kuò)展
- Flask-RESTful:構(gòu)建 REST API,自動(dòng)解析請(qǐng)求數(shù)據(jù)。
- Flask-WTF:集成 WTForms,處理表單驗(yàn)證和CSRF保護(hù)。
性能優(yōu)化
- 對(duì)于大文件上傳,使用流式處理或分塊傳輸。
- 啟用
gzip
壓縮減少數(shù)據(jù)傳輸量。
測試請(qǐng)求
使用 Flask 測試客戶端模擬請(qǐng)求:
with app.test_client() as client: response = client.post('/api', data={'username': 'test'}, headers={'Content-Type': 'multipart/form-data'}) assert response.status_code == 200
七、錯(cuò)誤處理與調(diào)試技巧
1. 優(yōu)雅處理數(shù)據(jù)解析錯(cuò)誤
在解析客戶端數(shù)據(jù)時(shí),可能會(huì)遇到格式錯(cuò)誤或非法內(nèi)容,需合理捕獲異常:
@app.route('/parse-json', methods=['POST']) def parse_json(): try: data = request.get_json() if data is None: raise ValueError("Invalid JSON") # 處理數(shù)據(jù)... except ValueError as e: return jsonify({"error": str(e)}), 400
關(guān)鍵點(diǎn):
- 使用
silent=True
時(shí),即使解析失敗也不會(huì)拋出異常,但需手動(dòng)檢查data
是否為None
。 - 針對(duì)文件上傳錯(cuò)誤,可檢查
request.files
是否存在且文件對(duì)象有效。
2. 調(diào)試請(qǐng)求數(shù)據(jù)的實(shí)用方法
在開發(fā)過程中,快速查看原始請(qǐng)求數(shù)據(jù)有助于定位問題:
@app.route('/debug', methods=['POST']) def debug_endpoint(): print("Headers:", request.headers) print("Raw Data:", request.data.decode('utf-8')) print("Form Data:", request.form) return "Debug information logged"
工具推薦:
- Postman:模擬復(fù)雜請(qǐng)求(如 multipart/form-data 或自定義 headers)。
- curl 命令:快速測試 API 接口:
curl -X POST http://localhost:5000/api -H "Content-Type: application/json" -d '{"key": "value"}'
八、安全加固策略
1. 防范常見攻擊
CSRF 保護(hù):使用
Flask-WTF
擴(kuò)展自動(dòng)生成和驗(yàn)證 CSRF Token:
from flask_wtf.csrf import CSRFProtect csrf = CSRFProtect(app)
在表單中添加隱藏字段:
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
SQL 注入防護(hù):始終使用 ORM(如 SQLAlchemy)或參數(shù)化查詢,避免拼接 SQL 字符串。
XSS 防護(hù):對(duì)用戶輸入的內(nèi)容進(jìn)行轉(zhuǎn)義(Flask 模板默認(rèn)自動(dòng)轉(zhuǎn)義)。
2. 文件上傳安全實(shí)踐
- 限制文件擴(kuò)展名:
allowed_extensions = {'png', 'jpg', 'jpeg'} filename = uploaded_file.filename if '.' not in filename or filename.split('.')[-1].lower() not in allowed_extensions: return "Invalid file type", 400
- 防止路徑遍歷:使用
secure_filename
處理文件名:
from werkzeug.utils import secure_filename safe_filename = secure_filename(uploaded_file.filename) uploaded_file.save(f'uploads/{safe_filename}')
九、異步與性能優(yōu)化
1. 異步處理大請(qǐng)求
使用 async/await
處理耗時(shí)操作(需 Flask 2.0+ 支持異步視圖):
@app.route('/async-upload', methods=['POST']) async def async_upload(): data = await request.get_data() # 異步處理數(shù)據(jù)(如寫入數(shù)據(jù)庫) return "Processing completed"
適用場景:
- 大文件上傳后的后臺(tái)處理(如視頻轉(zhuǎn)碼)。
- 高并發(fā)下的非阻塞 IO 操作。
2. 性能調(diào)優(yōu)建議
配置請(qǐng)求體大小限制:
app.config['MAX_CONTENT_LENGTH'] = 100 * 1024 * 1024 # 限制為100MB
啟用壓縮:通過 Nginx 或 GzipMiddleware 壓縮響應(yīng)數(shù)據(jù):
from flask_compress import Compress Compress(app)
十、與其他技術(shù)棧集成
1. 結(jié)合前端框架處理數(shù)據(jù)
- React/Vue 表單提交:確保前端
Content-Type
與后端匹配:
// 使用FormData處理文件上傳 const formData = new FormData(); formData.append('file', fileInput.files[0]); fetch('/api/upload', { method: 'POST', body: formData });
- AJAX 請(qǐng)求處理:Flask 自動(dòng)解析
application/json
,前端需明確設(shè)置 headers:
fetch('/api/data', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ key: 'value' }) });
2. 擴(kuò)展數(shù)據(jù)格式支持(如 XML)
若需解析 XML 請(qǐng)求,可自定義解析邏輯:
from xml.etree import ElementTree @app.route('/xml', methods=['POST']) def parse_xml(): xml_data = request.data root = ElementTree.fromstring(xml_data) value = root.find('key').text return jsonify({"value": value})
十一、實(shí)戰(zhàn)案例:構(gòu)建RESTful API
1. 用戶注冊接口
處理混合數(shù)據(jù)(JSON + 文件頭像上傳):
@app.route('/register', methods=['POST']) def register(): # 解析JSON數(shù)據(jù) user_data = request.get_json() username = user_data.get('username') # 處理頭像文件 avatar = request.files.get('avatar') if avatar: avatar.save(f'avatars/{secure_filename(avatar.filename)}') # 保存用戶到數(shù)據(jù)庫(偽代碼) save_user(username) return jsonify({"status": "success"})
2. 分頁查詢接口
結(jié)合查詢參數(shù)與數(shù)據(jù)過濾:
@app.route('/articles', methods=['GET']) def get_articles(): page = request.args.get('page', 1, type=int) per_page = request.args.get('per_page', 10, type=int) articles = Article.query.paginate(page=page, per_page=per_page) return jsonify({ "data": [article.to_dict() for article in articles.items], "total_pages": articles.pages })
十二、總結(jié)
Flask 的請(qǐng)求數(shù)據(jù)獲取機(jī)制兼顧靈活性與簡潔性,開發(fā)者需根據(jù)實(shí)際場景選擇合適的方法:
- 基礎(chǔ)場景:直接使用
request.args
、request.form
、request.json
。 - 復(fù)雜場景:結(jié)合流式處理、異步操作或第三方庫擴(kuò)展功能。
- 安全優(yōu)先:始終驗(yàn)證輸入、限制資源、防范常見攻擊。
通過合理設(shè)計(jì)數(shù)據(jù)流和錯(cuò)誤處理機(jī)制,可以構(gòu)建出高效、健壯的 Web 應(yīng)用。
到此這篇關(guān)于Flask請(qǐng)求數(shù)據(jù)獲取方法詳解的文章就介紹到這了,更多相關(guān)Flask請(qǐng)求數(shù)據(jù)獲取內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python標(biāo)準(zhǔn)庫inspect的具體使用方法
本篇文章主要介紹了Python標(biāo)準(zhǔn)庫inspect的具體使用方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-12-12pyinstaller將python程序打包為可執(zhí)行文件
這篇文章主要介紹了pyinstaller將python程序打包為可執(zhí)行文件,pyinstaller是一個(gè)python打包工具,它將python程序及所需依賴都打包成一個(gè)可執(zhí)行文件2022-08-08Python利用帶權(quán)重隨機(jī)數(shù)解決抽獎(jiǎng)和游戲爆裝備問題
帶權(quán)重隨機(jī)數(shù)即是隨機(jī)數(shù)各個(gè)區(qū)間段被抽中的概率根據(jù)權(quán)重而不同,這里我們就來看一下Python利用帶權(quán)重隨機(jī)數(shù)解決抽獎(jiǎng)和游戲爆裝備問題的方法,首先還是來進(jìn)一步解釋帶權(quán)隨機(jī)數(shù):2016-06-06Python利用yield?form實(shí)現(xiàn)異步協(xié)程爬蟲
這篇文章主要為大家詳細(xì)介紹了Python如何利用yield?form實(shí)現(xiàn)異步協(xié)程爬蟲。其實(shí)這是很古老的用法了,現(xiàn)在大多用的aiohttp庫實(shí)現(xiàn),這篇記錄僅僅用做個(gè)人的協(xié)程底層實(shí)現(xiàn)的學(xué)習(xí),希望對(duì)大家有所幫助2022-11-11Python實(shí)現(xiàn)對(duì)字符串的加密解密方法示例
這篇文章主要介紹了Python實(shí)現(xiàn)對(duì)字符串的加密解密方法,結(jié)合實(shí)例形式分析了Python使用PyCrypto模塊進(jìn)行DES加密解密的相關(guān)操作技巧,需要的朋友可以參考下2017-04-04新手該如何學(xué)python怎么學(xué)好python?
怎么學(xué)好python?怎么靈活應(yīng)用python?2008-10-10Django DRF認(rèn)證組件流程實(shí)現(xiàn)原理詳解
這篇文章主要介紹了Django DRF認(rèn)證組件流程實(shí)現(xiàn)原理詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08Python循環(huán)語句之while循環(huán)和for循環(huán)詳解
在Python中,循環(huán)語句用于重復(fù)執(zhí)行一段代碼,直到滿足某個(gè)條件為止,在Python中,有兩種主要的循環(huán)語句:for循環(huán)和while循環(huán),本文就來給大家介紹一下這兩個(gè)循環(huán)的用法,需要的朋友可以參考下2023-08-08一文帶你探索Python中15個(gè)常見的魔術(shù)方法
在Python中,特殊方法(也稱為魔術(shù)方法)是由Python解釋器自動(dòng)調(diào)用的,我們不需要手動(dòng)調(diào)用它們,本文小編為大家整理了15個(gè)常見特殊方法的實(shí)現(xiàn),希望對(duì)大家有所幫助2024-01-01