怎么給測(cè)試開(kāi)發(fā)框架 FastAPI 編個(gè)接口?
請(qǐng)求處理和返回響應(yīng)是任何一個(gè)開(kāi)發(fā)框架最核心的內(nèi)容。這篇文章主要講 FastAPI 中如何處理用戶的請(qǐng)求參數(shù)和響應(yīng)。

url 路徑參數(shù)
URL 路徑參數(shù)指的是通過(guò)在 URL 的斜杠后面?zhèn)鬟f的參數(shù)。比如我們要訪問(wèn) id 為 2 的 project, 則可以訪問(wèn) /project/2 這個(gè) URL。
但是這個(gè) 2 是每次都會(huì)變的,被稱為 URL 路徑參數(shù)。
在 FastAPI 中,用花括號(hào) {id} 表示動(dòng)態(tài)變化的 URL 參數(shù), 然后在函數(shù)中,通過(guò)同名的 id 作為參數(shù)接收。
@app.get('/project/{id}')
def project(id):
? ?return id
查詢字符串參數(shù)(query string)
和 路徑參數(shù)類似,你也可以通過(guò)查詢字符串的形式傳遞 id。查詢字符串就是在 url 中通過(guò) ? 號(hào)后面加參數(shù)。比如 /project/?id=2 這種形式。
使用上和路徑參數(shù)差不多,也是通過(guò) id 傳遞到函數(shù)當(dāng)中。當(dāng)找不到路徑參數(shù)時(shí),會(huì)在 query string 中查詢字段。
# query string@app.get('/project/')def project(id): ? ?return id
獲取 header
有時(shí)候在請(qǐng)求中需要獲取 header 當(dāng)中的數(shù)據(jù),比如在請(qǐng)求中經(jīng)常會(huì)在 Authorization 中獲取 token 值。
則可以在視圖函數(shù)中添加?authorization=Header(None)
?的關(guān)鍵字參數(shù),表示通過(guò) authorization 變量獲取 header 中的 Authorization 字段值。
注意參數(shù)名一定要和 header 中字段的名稱一致。
from fastapi import Header
@app.get('/project/')
def project(authorization=Header(None)):
? ?return authorization
獲取 form 表單數(shù)據(jù)
有時(shí)候在請(qǐng)求中需要獲取 form 表單當(dāng)中的數(shù)據(jù),比如用戶傳過(guò)來(lái)的用戶名和密碼。
則可以通過(guò) username 和 password 分別接受 form 表單中的用戶名和密碼。變量名同樣和傳入的數(shù)據(jù)字段保持一致。
from?fastapi?import?Form@app.get('/project/')def?project(username=Form(None), password=Form(None)): ? ?? ? ? return?username
獲取 body
獲取 body 和 header 類似,不同的是變量獲取的是所有 body 數(shù)據(jù)字段,而不是和 header 那樣,必須填入指定的參數(shù)名。
比如可以通過(guò)?item = Body(None)
?item 變量接收所有 body 數(shù)據(jù)。
需要注意的是:FastAPI 中 Body() 對(duì)象接收的是 JSON 格式數(shù)據(jù), 如果想接收表單類型數(shù)據(jù),需要通過(guò) Form()
@app.post('/login/')
def project(user = Body(None)):
? ?return user
{
? ?"username": "yuz",
? ?"pwd": 123
}
則該接口中 user 可以獲取到以上數(shù)據(jù)。
關(guān)于參數(shù)的其他說(shuō)明
FastAPI 給每種參數(shù)類型都定義了對(duì)應(yīng)的對(duì)象:
Path
Query
Body
Form
File
其實(shí),獲取路徑參數(shù)可以這樣:
@app.get('/project/{id}')def project(id=Path(...)):
? return id獲取 query string 可以是這樣:@app.get('/project/{id}')def project(id=Query(...)):
? return id
注意:header,query, path 都必須要有對(duì)應(yīng)的字段才能讀取到,但是 Body 是把所有的字段都讀取出來(lái)。
直接使用 request 對(duì)象
@app.get("/items/{item_id}")?
def read_root(item_id: str, request: Request): ? ?
client_host = request.client.host ? ?
? ? ? ? return {"client_host": client_host, "item_id": item_id}
使用 request 對(duì)象獲取請(qǐng)求對(duì)象非常方便。當(dāng)時(shí)獲取 form 表單這樣的數(shù)據(jù)只能調(diào)用 request.form() 方法,
這里得到的是一個(gè)協(xié)程對(duì)象。所以需要采用異步方式處理:
async def user(req: Request):
? ?user = await req.form()
或者使用 asyncio 運(yùn)行
def user(req: Request):
? ?user = asyncio.run(req.form())
要直接獲取 form 表單,也可以直接用 Form 對(duì)象。
默認(rèn)返回 JSON
直接返回字典或者列表
@app.get('/project/')
def project():
? ?return {"msg": "projects"}
狀態(tài)碼和響應(yīng) Header
def project():
? ?return JSONResponse(
? ? ? ?{"msg": "hello"},
? ? ? ?status_code=200,
? ? ? ?headers={'you': 'ok'}
? ?)
返回 HTML
def?project():? ? ?
? ? ? content?=?""" ? ?
? ? ? <html>?
? ? ? ? ? ? ? <h1 style="color:red">hello world</h1> ??
? ? ? </html> ? ?
? ? ? """???
? ? ? return?HTMLResponse(content)
返回文件
讀取文件一定要先安裝一個(gè)庫(kù) aiofile。
pip install aiofiles
然后使用 FileResponse
def project():
? ?return FileResponse('yy.jpg')
或者直接下載文件:
def?project():? ? ??
return?FileResponse('文件路徑.xls', filename='下載的文件.xls')
返回視頻
def?file(): ? ?
? ? ? file?=?open("demo.mp4",?'rb') ??
? ? ? return?StreamingResponse(file, media_type='video/mp4')
但是這個(gè)會(huì)一次性讀取視頻,如果很大,加載速度會(huì)很慢:

最好的方式是通過(guò)生成器一次返回指定大小的數(shù)據(jù):
def get_video(file):
? ?with open(file, 'rb') as f:
? ? ? ?while True:
? ? ? ? ? ?chuck = f.read(5000)
? ? ? ? ? ?if chuck:
? ? ? ? ? ? ? ?yield chuck
? ? ? ? ? ?else:
? ? ? ? ? ? ? ?break
def file():
? ?return StreamingResponse(
? ? ? ?get_video('抖音拍攝-吃蘋果-花絮1.mp4'),
? ? ? ?media_type='video/mp4'
? ? ? ?)
大家還有疑惑的地方,歡迎評(píng)論區(qū)留言呀~
聲明:本文為檸檬班雨澤老師原創(chuàng),轉(zhuǎn)載請(qǐng)注明出處!