呆鳥云:發(fā)布本系列旨在推廣 FastAPI 以及推進 FastAPI 中文官檔翻譯,目前杭棵,已完成 98% 的中文官檔翻譯,如果您對 FastAPI 有興趣氛赐,可以為這個很贊的開源項目做些貢獻魂爪,比如校譯、翻譯艰管、審閱等滓侍。
開源項目的發(fā)展離不開大家的支持。當(dāng)然最簡單的就是在 Github 上點 Star 了牲芋。
如果覺得 FastAPI 不錯撩笆,您也可以轉(zhuǎn)發(fā)、轉(zhuǎn)載本文缸浦,讓更多人知道 Python 還有這么簡單浇衬、快速的后端支持庫。
FastAPI 官檔地址:https://fastapi.tiangolo.com/zh/
下面先列出幾個需要 Review 的 PR餐济,希望大家多多參與。
- https://github.com/tiangolo/fastapi/pull/3826
- https://github.com/tiangolo/fastapi/pull/3827
- https://github.com/tiangolo/fastapi/pull/3828
- https://github.com/tiangolo/fastapi/pull/3829
- https://github.com/tiangolo/fastapi/pull/3830
- https://github.com/tiangolo/fastapi/pull/3832
- https://github.com/tiangolo/fastapi/pull/3793
- https://github.com/tiangolo/fastapi/pull/3795
- https://github.com/tiangolo/fastapi/pull/3796
以下為正文胆剧。
FastAPI 使用 Python 字符串格式化語法聲明路徑參數(shù)(變量):
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id):
return {"item_id": item_id}
這段代碼把路徑參數(shù) item_id
的值傳遞給路徑函數(shù)的參數(shù) item_id
絮姆。
運行示例,訪問 http://127.0.0.1:8000/items/foo秩霍,返回的響應(yīng)如下:
{"item_id":"foo"}
聲明路徑參數(shù)的類型
使用 Python 標(biāo)準類型注解篙悯,聲明路徑操作函數(shù)中路徑參數(shù)的類型。
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: int):
return {"item_id": item_id}
本例把 item_id
的類型聲明為 int
铃绒。
!!! check "檢查"
類型聲明將為函數(shù)提供錯誤檢查鸽照、代碼補全等編輯器支持。
數(shù)據(jù)轉(zhuǎn)換
運行示例并訪問 http://127.0.0.1:8000/items/3颠悬,返回的響應(yīng)如下:
{"item_id":3}
!!! check "檢查"
注意矮燎,函數(shù)接收并返回的值是 `3`( `int`)定血,不是 `"3"`(`str`)。
**FastAPI** 通過類型聲明自動**解析**诞外。
數(shù)據(jù)校驗
通過瀏覽器訪問 http://127.0.0.1:8000/items/foo澜沟,接收如下 HTTP 錯誤信息:
{
"detail": [
{
"loc": [
"path",
"item_id"
],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
}
這是因為路徑參數(shù) item_id
的值 ("foo"
)的類型不是 int
。
值的類型不是 int
而是浮點數(shù)(float
)時也會顯示同樣的錯誤峡谊,比如: http://127.0.0.1:8000/items/4.2茫虽。
!!! check "檢查"
**FastAPI** 使用 Python 類型聲明實現(xiàn)了數(shù)據(jù)校驗。
注意既们,上面的錯誤指明了未通過校驗的具體原因濒析。
這在開發(fā)調(diào)試與 API 交互的代碼時非常有用。
查看文檔
訪問 http://127.0.0.1:8000/docs啥纸,查看自動生成的 API 文檔:
!!! check "檢查"
還是使用 Python 類型聲明号杏,**FastAPI** 提供了(集成 Swagger UI 的)API 文檔。
注意脾拆,路徑參數(shù)的類型是整數(shù)馒索。
基于標(biāo)準的好處,備選文檔
FastAPI 使用 OpenAPI 生成概圖名船,所以能兼容很多工具绰上。
FastAPI 還內(nèi)置了 ReDoc 生成的備選 API 文檔,可在此查看 http://127.0.0.1:8000/redoc:
同樣渠驼,還有很多兼容工具蜈块,包括多種語言的代碼生成工具。
Pydantic
FastAPI 充分地利用了 Pydantic 的優(yōu)勢迷扇,用它在后臺校驗數(shù)據(jù)百揭。眾所周知,Pydantic 擅長的就是數(shù)據(jù)校驗蜓席。
同樣器一,str
、float
厨内、bool
以及很多復(fù)合數(shù)據(jù)類型都可以使用類型聲明祈秕。
下一章介紹詳細內(nèi)容。
順序很重要
有時雏胃,路徑操作中的路徑是寫死的请毛。
比如要使用 /users/me
獲取當(dāng)前用戶的數(shù)據(jù)。
然后還要使用 /users/{user_id}
瞭亮,通過用戶 ID 獲取指定用戶的數(shù)據(jù)方仿。
由于路徑操作是按順序依次運行的,因此,一定要在 /users/{user_id}
之前聲明 /users/me
:
from fastapi import FastAPI
app = FastAPI()
@app.get("/users/me")
async def read_user_me():
return {"user_id": "the current user"}
@app.get("/users/{user_id}")
async def read_user(user_id: str):
return {"user_id": user_id}
否則仙蚜,/users/{user_id}
將匹配 /users/me
此洲,F(xiàn)astAPI 會認為正在接收值為 "me"
的 user_id
參數(shù)。
預(yù)設(shè)值
路徑操作使用 Python 的 Enum
類型接收預(yù)設(shè)的路徑參數(shù)鳍征。
創(chuàng)建 Enum
類
導(dǎo)入 Enum
并創(chuàng)建繼承自 str
和 Enum
的子類黍翎。
通過從 str
繼承,API 文檔就能把值的類型定義為字符串艳丛,并且能正確渲染匣掸。
然后,創(chuàng)建包含固定值的類屬性氮双,這些固定值是可用的有效值:
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name == ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
!!! info "說明"
Python 3.4 及之后版本支持枚舉(即 enums)碰酝。
!!! tip "提示"
**AlexNet**、**ResNet**戴差、**LeNet** 是機器學(xué)習(xí)<abbr title="技術(shù)上來說是深度學(xué)習(xí)模型架構(gòu)">模型</abbr>送爸。
聲明路徑參數(shù)
使用 Enum 類(ModelName
)創(chuàng)建使用類型注解的路徑參數(shù):
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name == ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
查看文檔
API 文檔會顯示預(yù)定義路徑參數(shù)的可用值:
使用 Python 枚舉類型
路徑參數(shù)的值是枚舉的元素。
比較枚舉元素
枚舉類 ModelName
中的枚舉元素支持比較操作:
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name == ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
獲取枚舉值
使用 model_name.value
或 your_enum_member.value
獲取實際的值(本例中為字符串):
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name == ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
!!! tip "提示"
使用 `ModelName.lenet.value` 也能獲取值 `"lenet"`暖释。
返回枚舉元素
即使嵌套在 JSON 請求體里(例如袭厂, dict
),也可以從路徑操作返回枚舉元素球匕。
返回給客戶端之前纹磺,要把枚舉元素轉(zhuǎn)換為對應(yīng)的值(本例中為字符串):
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name == ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
客戶端中的 JSON 響應(yīng)如下:
{
"model_name": "alexnet",
"message": "Deep Learning FTW!"
}
包含路徑的路徑參數(shù)
假設(shè)路徑操作的路徑為 /files/{file_path}
。
但需要 file_path
中也包含路徑亮曹,比如橄杨,home/johndoe/myfile.txt
。
此時照卦,文件 URL 是這樣的:/files/home/johndoe/myfile.txt
式矫。
OpenAPI 支持
OpenAPI 不支持聲明包含路徑的路徑參數(shù),因為這會導(dǎo)致測試和定義更加困難役耕。
不過采转,仍可使用 Starlette 內(nèi)置工具在 FastAPI 中實現(xiàn)這一功能。
而且不影響文檔正常運行瞬痘,但是不會添加該參數(shù)包含路徑的說明氏义。
路徑轉(zhuǎn)換器
直接使用 Starlette 的選項聲明包含路徑的路徑參數(shù):
/files/{file_path:path}
本例中,參數(shù)名為 file_path
图云,結(jié)尾部分的 :path
說明該參數(shù)應(yīng)匹配路徑。
用法如下:
from fastapi import FastAPI
app = FastAPI()
@app.get("/files/{file_path:path}")
async def read_file(file_path: str):
return {"file_path": file_path}
!!! tip "提示"
注意邻邮,包含 `/home/johndoe/myfile.txt` 的路徑參數(shù)要以斜杠(`/`)開頭竣况。
本例中的 URL 是 `/files//home/johndoe/myfile.txt`。注意,`files` 和 `home` 之間要使用**雙斜杠**(`//`)丹泉。
小結(jié)
通過簡短情萤、直觀的 Python 標(biāo)準類型聲明,FastAPI 可以支持:
- 編輯器支持:錯誤檢查摹恨,代碼自動補全等
- 數(shù)據(jù)解析
- 數(shù)據(jù)校驗
- API 注解和 API 文檔
只需要聲明一次即可筋岛。
這可能是除了性能以外,FastAPI 與其它框架相比的主要優(yōu)勢晒哄。