Learning Objectives
- 用 request.args、request.form、request.get_json() 讀取不同位置的資料
- 說明 get 與 [] 的差別,以及缺少參數時的結果
- 說明表單與查詢字串的值都是字串,用 type=int 轉換
- 正確說明 GET 與 POST 的語意與差別,包括 POST 並不會自動加密
- 讀取方法、路徑、標頭與 Cookie
資料放在請求的哪裡
使用者可以從不同地方把資料送給伺服器:搜尋關鍵字放在網址,表單內容放在請求的內容,API 則常送 JSON。第 1 課看過請求的結構,Flask 把解析好的結果都放在 request 物件裡:
from flask import request
| 資料在哪 | 例子 | 怎麼讀 |
|---|---|---|
| 網址的路徑 | /note/3 |
view 函數的引數(上一課) |
| 查詢字串 | /search?q=flask |
request.args |
| 表單內容 | <form method="post"> |
request.form |
| JSON 內容 | API 請求 | request.get_json() |
| 標頭 | User-Agent: ... |
request.headers |
| Cookie | Cookie: theme=dark |
request.cookies |
request 看起來是全域變數,但每個請求讀到的都是自己的內容。它只能在處理請求的期間使用。
逐步看:查詢字串
request.args 用起來像字典。注意 raw 和 page 的型別差別,以及第二次請求 page=abc 的結果。
GET 與 POST 的差別
| GET | POST | |
|---|---|---|
| 語意 | 取得資料,不應該改變伺服器上的資料 | 送出資料,通常會造成改變 |
| 資料放哪 | 網址的查詢字串 | 請求的內容 |
| 重新整理或加書籤 | 可以重複,不會改到資料 | 瀏覽器會詢問是否重新送出 |
| 網址可以分享 | 可以,適合搜尋、篩選 | 不行,資料不在網址裡 |
怎麼選?看語意:搜尋、篩選、翻頁用 GET;新增留言、登入、刪除用 POST。搜尋爬蟲和瀏覽器的預先載入可能自動開啟 GET 連結,如果 GET 會改資料,資料就可能被意外改掉。
常見的誤解:POST 比 GET 安全。 POST 只是把資料放在內容而不是網址,沒有 HTTPS 的話,傳輸過程一樣看得到。它的好處是資料不會留在瀏覽器歷史、伺服器的網址紀錄裡,所以密碼這類資料不應該放在網址。真正保護傳輸的是 HTTPS,保護資料的是伺服器端的權限檢查。
逐步看:表單與 JSON
client.post(網址, data=字典) 模擬表單送出;json=字典 模擬送 JSON。兩次都傳了 views 為 3,比較 view 函數收到的型別,再看送錯內容時的結果。
逐步看:方法、路徑、標頭與 Cookie
request 還有很多屬性。這裡送出一個帶自訂標頭和 Cookie 的請求,把常用的都印出來。
動手做:搜尋與回饋 API
完成兩個 view 函數:
search:讀取查詢字串q(預設空字串,去掉前後空白)和page(整數,預設 1,不是數字時也用 1),回傳搜尋「關鍵字」第 N 頁feedback:用silent=True讀取 JSON。沒有 JSON 或沒有text時回傳{'error': '需要 text'}與 400;否則回傳{'length': 字數}與 201
程式最下面的測試不要改。
想一想
下面的程式會印出什麼?
from flask import Flask, request
app = Flask(__name__)
@app.route('/n')
def n():
a = request.args.get('x')
b = request.args.get('x', 0, type=int)
return f'{type(a).__name__} {b}'
print(app.test_client().get('/n?x=abc').get_data(as_text=True))
request.form['title'] 在表單沒有 title 時會怎樣?
關於 GET 與 POST,下面哪個說法正確?
「搜尋課程」的功能應該用哪個方法?
呼叫 request.get_json() 時,請求的 Content-Type 是 text/plain,結果是?
重點整理
- 查詢字串用
request.args,表單用request.form,JSON 用request.get_json() .get()找不到時回傳預設值;[]找不到時 Flask 回 400- 查詢字串與表單的值都是字串,用
type=int轉換;JSON 有自己的型別 get_json():類型不對回 415,語法錯誤回 400;silent=True改成回傳None- 依語意選方法:取得資料用 GET,改變資料用 POST;POST 不等於加密,保護傳輸要用 HTTPS
- 標頭、Cookie、表單都是請求方自己送的,不能直接信任
讀完請求,下一課看怎麼控制回應:狀態碼、標頭、轉址,以及在每個請求前後都要做的事。