FastAPI--路由(2)


一、概述

路由方法有 GET, POST, PUT, PATCH, DELETE 和 OPTIONS。

import uvicorn
from fastapi import FastAPI

app = FastAPI()

@app.post("/")
@app.put("/")
@app.delete("/")
@app.get("/")
@app.options("/")
@app.head("/")
@app.patch("/")
@app.trace("/")
async def root():
    return {"message": "Hello 454533333343433World"}

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)

 

二、路由Route上參數獲取和校驗

一般我們的路由分會靜態和動態,靜態路由就是參數是固定寫死,也就是訪問地址是寫死的,而動態地址,就是需要動態的生成,類似簡書的博文的地址94710ed35b92就是動態,其實和Bottle和Flask一樣。

https://www.jianshu.com/p/94710ed35b92

代碼如下:

import uvicorn
from fastapi import FastAPI

app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(item_id):
    return {"item_id": item_id}
if __name__ == '__main__': uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)

 

上述的示例代碼中的item_id 就是一個動態的參數,你可以隨意傳一個進來。

http://127.0.0.1:8000/items/ask

 

 

然后就是和bottle(微型Web框架)一樣也可以對傳入的參數進行數據驗證的定義: 如:

import uvicorn
from fastapi import FastAPI

app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(item_id: int):
    return {"item_id": item_id}

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)

 

item_id: int 這種情況item_id必須是可以轉為int類似的數據,否則,肯定會報錯!

http://127.0.0.1:8000/items/ask

它會給出提示,必須是int類型。返回的HTTP狀態碼為422

 

關於路由覆蓋問題: 如下兩個路由地址:

import uvicorn
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}

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)

上面兩個路由同時存在的話,會按照匹配規則進行匹配。什么意思呢?

@app.get("/users/me") 表示精確匹配

@app.get("/users/{user_id}") 表示模糊匹配

下面我來驗證一下。

http://127.0.0.1:8000/users/me

 

 可以看到,它匹配了是第一條。注意:只有正常情況下,才會返回HTTP 200

 

http://127.0.0.1:8000/users/123

 

 發現它是匹配的第2個路徑。

 

查詢路徑參數和參數校驗

關於查詢參數,其實就是在使用POSTMAN 提交的時候的參數信息: 如:

http://127.0.0.1:8000/items/?skip=0&limit=10

skip=0&limit 就是所謂的查詢參數。

import uvicorn
from fastapi import FastAPI

app = FastAPI()

fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]

@app.get("/items/")
async def read_item(skip: int = 0, limit: int = 10):
    return fake_items_db[skip: skip + limit]

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)

 

第一種訪問的情況:

http://127.0.0.1:8000/items/

我們發現,它返回的是list所有數據。這是為什么呢?來,我來細細品一下代碼。

在這個url中,並沒有傳入參數skip和limit,那么它會使用默認值,分別是0,100

那么fake_items_db[skip: skip + limit] 等同於fake_items_db[0:10]

看到這里,學過python基礎知識的,應該明白,這是列表切片。

 

第二種訪問情況:

http://127.0.0.1:8000/items/?skip=1

 

返回了最后2條數據,第一條沒有顯示。因為此時fake_items_db[skip: skip + limit] 等同於fake_items_db[1:10]

 

第三種訪問情況:

http://127.0.0.1:8000/items/?skip=abc

 

 提示錯誤信息,值不是整形,HTTP狀態碼為:422

 

多路徑和查詢參數

所謂的多路徑和查詢參數就是URL上包含了有動態的參數,還有需要通過&分隔符提交的參數,這情況,通常再GET提交的中也很常見,那么如何處理吶?

import uvicorn
from fastapi import FastAPI

app = FastAPI()

@app.get("/users/{user_id}/items/{item_id}")
async def read_user_item(
    user_id: int, item_id: str, q: str = None, short: bool = False
):
    item = {"item_id": item_id, "owner_id": user_id}
    if q:
        item.update({"q": q})
    if not short:
        item.update(
            {"description": "This is an amazing item that has a long description"}
        )
    return item

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)

 

請求:

http://127.0.0.1:8000/users/123456/items/items_xinxiid/?q=assa&short=True

 注意:item.update 是python字典的一個語法。存在即更新,不存在,即添加。

其他邏輯我就不解釋了,仔細看也能明白。

 

請求:

http://127.0.0.1:8000/users/123456/items/items_xinxiid/?q=assa&short=False

 由於short=False,因此description值做了更新操作。

 

路徑參數和查詢參數的必選和可選

參數的可選和必選主要是通過是否給默認值來決定的,如:

 

import uvicorn
from fastapi import FastAPI

app = FastAPI()

@app.get("/items/{item_id}")
async def read_user_item(item_id: str, needy: str):
    item = {"item_id": item_id, "needy": needy}
    return item

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)

 

上述的代碼中 needy 沒有給與默認的值,當個沒提交這個值的時候,會提示錯誤:

http://127.0.0.1:8000/items/123456

還可以定義可選參數和必選的參數的提交類型: 其中還可以使用Optional來定義需要提交的數據類型: 如:

import uvicorn
from fastapi import FastAPI
from typing import Optional

app = FastAPI()

@app.get("/items/{item_id}")
async def read_user_item(item_id: str, limit: Optional[int] = None):
    item = {"item_id": item_id, "limit": limit}
    return item

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)

 

我們把查詢參數limit規定為了int類型,但是它是可選的的參數,設置為了None:

http://127.0.0.1:8000/items/ask

 

如果傳入的參數類型不對,就會報錯

http://127.0.0.1:8000/items/ask?limit=422w

路徑參數的枚舉

import uvicorn
from fastapi import FastAPI
from enum import Enum

app = FastAPI()

class ModelName(str, Enum):
    alexnet = "alexnet"
    resnet = "resnet"
    lenet = "lenet"

@app.get("/model/{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"}

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)

 

訪問地址:

http://127.0.0.1:8000/model/alexnet

 可以發現,它匹配了第一條規則。

 

查詢參數Query參數的其他校驗

在以前通常是使用wtform來定義提交的字段信息的類似或可選或長度類型。在Fastapi里面,我們是通過: from fastapi import FastAPI, Query 中的Query來定義,如:

import uvicorn
from fastapi import FastAPI, Query 
app = FastAPI()

@app.get("/items/")
async def read_items(q: str = Query(None, min_length=3,max_length=50,regex="^fixedquery")):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)

注意:參考文章中有一個小錯誤,regex必須在Query里面才能生效。

 

參數解釋:

q: str = Query(None, min_length=3,max_length=50,regex="^fixedquery") 意思是:q參數是可選的參數,但是如果填寫的話,最大長度必須是小於50內,且最小的長度必須大於3: 且需要符合regex的匹配

 

當然None可以修改為其他默認值,可以寫如:

q: q: str = Query('xiaozhong', min_length=3,max_length=50,regex="^fixedquery"))

注意:如果正則為^fixedquery$,表示精確匹配,q必須是fixedquery才行。前后左右多一點都不行。

為了下面的測試,我去掉了$

 

不傳q的情況下:

http://127.0.0.1:8000/items/

傳q的情況下且長度大於50:

http://127.0.0.1:8000/items/?q=fixedquery333333333333333333333333333333333333333333

傳q的情況下且長度小於3:

http://127.0.0.1:8000/items/?q=fixedquery333

查詢參數Query的參數正則校驗

http://127.0.0.1:8000/items/?q=433

查詢參數Query參數多值列表

 一般在我們的接口中很少說同一個參數提交多個值如:

http://127.0.0.1:8000/items/?q=foo&q=bar

但也不排查這種情況的存在,所以也可以定義我們的參數類似必須是列表的形式:

import uvicorn
from fastapi import FastAPI, Query
from typing import List

app = FastAPI()


@app.get("/items/")
async def read_items(q: List[str] = Query(["foo", "bar"])):
    # <!--也可以使用list直接代替List[str]:-->
    query_items = {"q": q}
    return query_items

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)

 

默認值:

http://127.0.0.1:8000/items/

非默認值:

http://127.0.0.1:8000/items/?q=123&q=456

 

路徑參數的其他校驗方式

對於查詢參數可以通過Query,同樣對於路徑參數也可以使用Fastapi自帶的Path來進行校驗。

import uvicorn
from fastapi import FastAPI, Path

app = FastAPI()

@app.get("/items/{item_id}")
async def read_items(
    q: str, item_id: int = Path(..., title="The ID of the item to get")
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)

 

http://127.0.0.1:8000/items/11?q=22

 

 對於路徑參數校驗中,還可以對item_id進行大於或等於的校驗如:

import uvicorn
from fastapi import FastAPI, Path

app = FastAPI()

@app.get("/items/{item_id}")
async def read_items(
        *, item_id: int = Path(..., title="The ID of the item to get", ge=1), q: str):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)

 

在上面代碼意思是,item_id必須是整數,而且必須大於等於1。其中ge=1表示大於等於1

 

傳入0就會報錯

http://127.0.0.1:8000/items/0?q=aa

 

 

 

本文參考鏈接:

http://www.zyiz.net/tech/detail-119883.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM