[英]catch errors using pydantic @validator decorator for fastapi input query
到目前為止,我有 2 個問題無法使用 docs/goole/stack info 解決:-)
1)當使用 model 作為 fastapi get 查詢的查詢輸入時,我應該如何捕獲 pydantic model 驗證器裝飾器拋出的 ValidationErrors?
語境:
我有一個 pydantic model:
class PointRankReqParams(BaseModel):
rat: Optional[Literal['2G', '3G', '4G', '5G']] = '3G'
h3resolution: Optional[int] = 5
input_srid: Optional[int] = 4326
bufferdistance: Optional[int] = 5000
x: float
y: float
@validator('h3resolution')
def h3resolution_bins(cls, v):
if v not in [4,5,6,7,8]:
raise ValueError('Hexabin size not permitted')
return v
和服務 GET 請求的 FastAPI 函數:
@router.get("/point/overall", summary="GET Ranking for given location point")
async def get_ranking_for_location_point(inputparams: PointRankReqParams = Depends(),token: str = Depends(oauth2_scheme)):
logger.debug("Here I am")
return {}
現在,當我的 curl 參數h3resolution超出定義范圍時,例如http://localhost:9000/rank/point/overall?rat=2G&h3resolution=9&input_srid=4326&bufferdistance=5000&x=21&y=21
在控制台中得到錯誤實際上是有道理的
py- | File "pydantic/main.py", line 406, in pydantic.main.BaseModel.__init__
py- | pydantic.error_wrappers.ValidationError: 1 validation error for PointRankReqParams
py- | h3resolution
py- | Hexabin size not permitted (type=value_error)
但是 FastAPI 向終端客戶端返回 HTTP 500 Internal Server Error。 我應該如何捕捉那些來自驗證器的異常?
2. 如何正確使用 Optional[Literal[...]] 構造?
我嘗試重新定義上面的示例以在 model 中使用:
class PointRankReqParams(BaseModel):
...
h3resolution: Optional[Literal[4,5,6,7,8]] = 5
But when I curl GET query eg http://localhost:9000/rank/point/overall?rat=2G&h3resolution=7&input_srid=4326&bufferdistance=5000&x=21&y=21
I receive 422 Unprocessable entry as h3resolution is being interpreted as string not integer:
{
"detail": [
{
"loc": [
"query",
"h3resolution"
],
"msg": "unexpected value; permitted: 4, 5, 6, 7, 8",
"type": "value_error.const",
"ctx": {
"given": "7",
"permitted": [
4,
5,
6,
7,
8
]
}
}
]
}
非常感謝!
這是一個非常好的問題,已經討論了好幾年,你可以查看這個github 問題。 不幸的是,對於如何處理它沒有達成共識, 文檔只顯示了一個使用普通 Python 類的簡單用例。 它與BaseModel
和dataclass
一起使用,直到您想要自定義驗證器或其他東西,FastAPI 的作者說:
具有單個 Pydantic model 用於查詢參數可以解釋為:
http://somedomain.com/?args={"k1":"v1","k2":"v2"}
或者
http://somedomain.com/?k1=v1&k2=v2
或許多其他選擇...
我們甚至沒有討論在 Pydantic 模型(和請求主體)中有效的子模型,但對於非主體參數(查詢、路徑等),行為將是未定義的。
go 沒有明顯的方法來解釋如何解釋它適用於所有情況(包括其他人的用例、未來用例等)。
因此,將它放在 FastAPI 中用於自定義用例並沒有什么意義,因為它非常主觀並且依賴於團隊的約定。
jimcarreer建議使用類似的東西:
class PagingQuery(BaseModel):
page: conint(ge=1)
page_size: conint(ge=1, le=250) = 50
@classmethod
async def depends(cls, page: int = 1, page_size: int = 50):
try:
return cls(page=page, page_size=page_size)
except ValidationError as e:
errors = e.errors()
for error in errors:
error['loc'] = ['query'] + list(error['loc'])
raise HTTPException(422, detail=errors)
@app.get("/example", tags=["basic"])
def example(paging: PagingQuery = Depends(PagingQuery.depends)):
return {"page": paging.page, "page_size": paging.page_size}
但這看起來很老套,我寧願遠離它。
回答你的第二個問題,查詢字符串只是一個字符串(如'age=20&name=John'
),鍵、值對只是字符串; 你已經指定了Literal
類型,所以不會有類型轉換,你會得到一個異常。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.