簡體   English   中英

使用 pydantic @validator 裝飾器捕獲錯誤以進行 fastapi 輸入查詢

[英]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 類的簡單用例。 它與BaseModeldataclass一起使用,直到您想要自定義驗證器或其他東西,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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM