FastAPI官檔精編006 - 路徑參數(shù)


呆鳥云:發(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餐济,希望大家多多參與。

以下為正文胆剧。


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ù)校驗蜓席。

同樣器一,strfloat厨内、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)建繼承自 strEnum 的子類黍翎。

通過從 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.valueyour_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)勢晒哄。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末睁宰,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子寝凌,更是在濱河造成了極大的恐慌柒傻,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件较木,死亡現(xiàn)場離奇詭異红符,居然都是意外死亡,警方通過查閱死者的電腦和手機伐债,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門预侯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人峰锁,你說我怎么就攤上這事萎馅。” “怎么了祖今?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵校坑,是天一觀的道長。 經(jīng)常有香客問我千诬,道長耍目,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任徐绑,我火速辦了婚禮邪驮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘傲茄。我一直安慰自己毅访,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布盘榨。 她就那樣靜靜地躺著喻粹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪草巡。 梳的紋絲不亂的頭發(fā)上守呜,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天,我揣著相機與錄音,去河邊找鬼查乒。 笑死弥喉,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的玛迄。 我是一名探鬼主播由境,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蓖议!你這毒婦竟也來了虏杰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤拒担,失蹤者是張志新(化名)和其女友劉穎嘹屯,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體从撼,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡州弟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了低零。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片婆翔。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖掏婶,靈堂內(nèi)的尸體忽然破棺而出啃奴,到底是詐尸還是另有隱情,我是刑警寧澤雄妥,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布最蕾,位于F島的核電站,受9級特大地震影響老厌,放射性物質(zhì)發(fā)生泄漏瘟则。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一枝秤、第九天 我趴在偏房一處隱蔽的房頂上張望醋拧。 院中可真熱鬧,春花似錦淀弹、人聲如沸丹壕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽菌赖。三九已至,卻和暖如春沐序,著一層夾襖步出監(jiān)牢的瞬間盏袄,已是汗流浹背忿峻。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留辕羽,地道東北人。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓垄惧,卻偏偏與公主長得像刁愿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子到逊,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容