【问题标题】:FastAPI Single Parameter Body cause Pydantic Validation ErrorFastAPI 单参数正文导致 Pydantic 验证错误
【发布时间】:2020-09-09 03:58:37
【问题描述】:

我有一个 POST FastAPI 方法。我不想构造一个类也不想查询字符串。所以,我决定申请Body() 方法。

@app.post("/test-single-int")
async def test_single_int(
    t: int = Body(...)
):
    pass

这是请求

POST http://localhost:8000/test-single-int/

{
  "t": 10
}

这就是响应

HTTP/1.1 422 Unprocessable Entity
date: Fri, 22 May 2020 10:00:16 GMT
server: uvicorn
content-length: 83
content-type: application/json
connection: close

{
  "detail": [
    {
      "loc": [
        "body",
        "s"
      ],
      "msg": "str type expected",
      "type": "type_error.str"
    }
  ]
}

但是,在尝试了很多样本​​后,我发现如果我有多个Body(),它们不会出错。例如,

@app.post("/test-multi-mix")
async def test_multi_param(
    s: str = Body(...),
    t: int = Body(...),
):
    pass

请求

POST http://localhost:8000/test-multi-mix/

{
  "s": "test",
  "t": 10
}

回应

HTTP/1.1 200 OK
date: Fri, 22 May 2020 10:16:12 GMT
server: uvicorn
content-length: 4
content-type: application/json
connection: close

null

有人对我的实现有任何想法吗?有错吗?这不是最佳实践吗?或者它是一个错误?

【问题讨论】:

    标签: python http-post httprequest fastapi pydantic


    【解决方案1】:

    使用 FastApi 从正文中获取任何数据:

    @app.post("/someurl")
    async def someMethod(body: dict):
        return body
    

    【讨论】:

      【解决方案2】:

      这不是一个错误,它是 Body 的行为方式,它存在于“扩展”请求参数如何文档outlines

      class Item(BaseModel):
          name: str
      
      class User(BaseModel):
          username: str
          full_name: str = None
      
      
      @app.put("/items/{item_id}")
      async def update_item(
          *,
          item_id: int,
          item: Item,
          user: User,
          importance: int = Body(..., gt=0),
          q: str = None
      ):
          pass
      

      此视图的有效请求正文为:

      {
          "item": {
              "name": "Foo",
              "tax": 3.2
          },
          "user": {
              "username": "dave",
              "full_name": "Dave Grohl"
          },
          "importance": 5
      }
      

      如果你真的想单独使用 Body 你必须指定embed=True,这个可以正常工作:

      @app.put("/items/{item_id}")
      async def update_item(
          *,
          item_id:int,
          importance: int = Body(..., gt=0, embed=True),
          q: str = None
      ):
          pass
      

      【讨论】:

        猜你喜欢
        • 2022-07-04
        • 2021-12-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-15
        • 2023-03-28
        • 2014-03-11
        • 1970-01-01
        相关资源
        最近更新 更多