Python:带有发布请求的 FastAPI 错误 422

Posted

技术标签:

【中文标题】Python:带有发布请求的 FastAPI 错误 422【英文标题】:Python: FastAPI error 422 with post request 【发布时间】:2020-05-12 16:54:11 【问题描述】:

我正在构建一个简单的 API 来测试数据库。当我使用获取请求时,一切正常,但如果我更改为发布,我会收到“无法处理的实体”错误:

这里是 FastAPI 代码:

from fastapi import FastAPI

app = FastAPI()

@app.post("/")
def main(user):
    return user

然后,我的请求使用 javascript

let axios = require('axios')

data =  
    user: 'smith' 


axios.post('http://localhost:8000', data)
    .then(response => (console.log(response.url)))

也使用 Python

import requests

url = 'http://127.0.0.1:8000'
data = 'user': 'Smith'

response = requests.post(url, json=data)
print(response.text)

我也尝试解析为 json,使用 utf-8 编码,并更改标题。没有什么对我有用。

【问题讨论】:

您是否启动了运行 fastapi 应用程序的服务器(如 uvicorn)? 【参考方案1】:

直接来自documentation:

函数参数将被识别如下:

如果路径中也声明了该参数,则将其用作路径参数。 如果参数是单数类型(如int、float、str、bool等),它将被解释为查询参数。 如果参数被声明为Pydantic模型的类型,它将被解释为请求body。”

因此,要创建一个接收带有用户字段的正文的 POST 端点,您可以执行以下操作:

from fastapi import FastAPI
from pydantic import BaseModel


app = FastAPI()


class Data(BaseModel):
    user: str


@app.post("/")
def main(data: Data):
    return data

【讨论】:

【参考方案2】:

就我而言,我是从不同的 python 项目中调用 python API 的

queryResponse = requests.post(URL, data= query)

我使用的是 data 属性,我将其更改为 json,然后它对我有用

queryResponse = requests.post(URL, json = query)

【讨论】:

谢谢!这也让我的工作......但我仍然希望我知道为什么通过数据(如帮助文件指令)传递字典会导致 422 错误状态代码。 我读到数据字段是用于 FormData 格式的......这似乎是一个用于传递 html 表单数据的 javascript 类。 github.com/tiangolo/fastapi/issues/3373【参考方案3】:

对于获取请求体的POST请求,需要如下操作

创建一个 Pydantic 基础模型用户

from pydantic import BaseModel

class User(BaseModel):
    user_name: str


@app.post("/")
def main(user: User):
   return user

【讨论】:

【参考方案4】:

FastAPI 基于 Python 类型提示,因此当您传递查询参数时,它接受 key:value 对,您需要以某种方式声明它.

即使是这样的事情也会起作用

from typing import Dict, Any
...
@app.post("/")
def main(user: Dict[Any, Any] = None):
    return user

Out: "user":"Smith"

但使用 Pydantic 方式更有效

class User(BaseModel):
    user: str

@app.post("/")
def main(user: User):
    return user

Out: "user":"Smith"

【讨论】:

【参考方案5】:

如果您正在使用fetch API 并且仍然得到 422 Unprocessable Entity,请确保您已设置 Content-Type 标头:

fetch(someURL, 
  method: "POST",
  headers: 
    "Content-type": "application/json"
  ,
  body
).then(...)

这解决了我的问题。在服务器端,我使用的是 Pydantic 模型,所以如果您不使用这些模型,请参阅上面的答案。

【讨论】:

不管怎样,直到我将 fastapi 从 0.63 版本更新到 0.70 之前,我才开始遇到问题。我一直用头撞墙,直到我看到你的反应。我最初使用 jquery,其中“类型”设置为“json”。我改变了我的保存功能,使用上面设置的 Content-type 的 fetch api,问题解决了!【参考方案6】:

就我而言,我的 FastAPI 端点需要的是表单数据而不是 JSON。因此,解决方法是发送表单数据而不是 JSON。 (注:对于node-js,FormData不可用,可以使用form-data)

【讨论】:

【参考方案7】:

here 发布的答案是正确的。当涉及到 JSON 发布请求时,应该使用 Pydantic 模型(关于表单数据,请查看here)。但是,如果不想使用 Pydantic 模型,他们也可以使用Body parameters。如果使用单个主体参数(如您的示例),则可以使用特殊的 Body parameter embed。下面是一个工作示例。

app.py

import uvicorn
from fastapi import Body, FastAPI

app = FastAPI()

@app.post("/")
async def main(user: str = Body(..., embed=True)):
    return "user": user
    
if __name__ == '__main__':
    uvicorn.run(app, host='127.0.0.1', port=8000, debug=True)

test.py

import requests

url = 'http://127.0.0.1:8000'
payload ="user": "foo"
resp = requests.post(url=url, json=payload)
print(resp.json())

【讨论】:

以上是关于Python:带有发布请求的 FastAPI 错误 422的主要内容,如果未能解决你的问题,请参考以下文章

18.FastAPI错误处理

尝试使用 websockets 从 FastAPI 获取实时数据流时如何修复错误(不支持的升级请求。)?

Azure 应用服务Python fastapi Function在Azure

python3.6 async/await 仍然与 fastAPI 同步工作

使用 FastAPI 的异步 SqlAlchemy:获取所有请求的单个会话

python:Fastapi - Cookie 和 Header