![](/img/trans.png)
[英]FastAPI: How to Fix '422 Unprocessable Entity' when sending a POST request using PHP
[英]Python: FastAPI error 422 with POST request when sending JSON data
我正在構建一個簡單的 API 來測試數據庫。 當我使用GET
請求時一切正常,但如果我更改為POST
,我會收到422 Unprocessable Entity
錯誤。
這是 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 requests
:
import requests
url = 'http://127.0.0.1:8000'
data = {'user': 'Smith'}
response = requests.post(url, json=data)
print(response.text)
我還嘗試解析為 JSON,使用utf-8
進行解析,並更改標頭,但對我沒有任何作用。
直接來自文檔:
函數參數將被識別如下:
- 如果參數也在path 中聲明,它將用作路徑參數。
- 如果參數是單一類型(如 int、float、str、bool 等),它將被解釋為查詢參數。
- 如果參數被聲明為Pydantic 模型的類型,它將被解釋為請求體。”
因此,要創建一個接收帶有用戶字段的正文的 POST 端點,您可以執行以下操作:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Data(BaseModel):
user: str
@app.post("/")
def main(data: Data):
return data
對於 POST Requests 接收請求體,需要做如下操作
創建 Pydantic 基礎模型用戶
from pydantic import BaseModel
class User(BaseModel):
user_name: str
@app.post("/")
def main(user: User):
return user
(如果不是像上面那樣的語法錯誤)從發布請求接收響應 422 可能有很多原因。
如果您使用的是 FastAPI,請使用內置的“/docs”路由在本地主機上進行測試,如果帖子在那里失敗,則可能是語法/邏輯錯誤,與您的帖子路由無關。 FastAPI 的這個特性非常有幫助。 注意 Post 請求不需要/期望 UI 上的標題,因為它為您提供了一個文本位置來填充它。
測試在可變主體端點上:您可以這樣設置:
@app.post('/test') async def function(objectName: dict = Body(...)):
使用任何 JSON 發送請求,如果仍然收到 422,則轉到下一步。
headers = {'Content-Type': 'application/json'};
這個錯誤似乎是在 FastAPI 完成之前 origin 掛斷的結果。
我從 Java 調用 FastAPI,它返回得太早了。
為了修復此錯誤,我添加了CompletableFuture<String>
的用法並使用HTTPClient.sendAsync
function,然后在 promise 上調用CompletableFuture.get
。
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"}
就我而言,我正在像這樣從不同的 python 項目調用 python API
queryResponse = requests.post(URL, data= query)
我正在使用數據屬性,我將其更改為 json,然后它對我有用
queryResponse = requests.post(URL, json = query)
就我而言,我的 FastAPI 端點需要表單數據而不是 JSON。 因此,解決方法是發送表單數據而不是 JSON。 (注意:對於node-js,FormData不可用,可以使用form-data )
此處發布的答案是正確的。 在發布請求時應該使用 Pydantic 模型(盡管關於表單數據,請參見此處)。 但是,如果不想使用 Pydantic 模型,他們也可以使用Body parameters 。 如果使用單個 body 參數(如您的示例中),您可以使用特殊的Body參數embed 。 下面是一個使用這個概念的工作示例。
應用程序.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)
測試.py
import requests
url = 'http://127.0.0.1:8000'
payload ={"user": "foo"}
resp = requests.post(url=url, json=payload)
print(resp.json())
如果您正在使用fetch
API 並且仍然獲得422 Unprocessable Entity ,請確保您已設置Content-Type標頭:
fetch(someURL, {
method: "POST",
headers: {
"Content-type": "application/json"
},
body
}).then(...)
這解決了我的問題。 在服務器端,我使用的是 Pydantic 模型,所以如果您不使用這些模型,請參閱上面的答案。
對我來說,問題是我的 POST 正文不包含端點正在尋找的所有屬性:
郵政
{
"gateway": "",
"nameservers": [],
"deleteWiFi": true,
"ssidPassword": ""
}
FastAPI python
class SubmitWiFi(BaseModel):
gateway: str
addresses: list[str] # missing
nameservers: list[str]
deleteWiFi: bool
ssid: str # missing
ssidPassword: str
@app.post("/submitWiFi")
async def submitWiFi(data: SubmitWiFi):
# my code
這不是一個描述性很強的錯誤,而且很難找到原因。
我在使用 FastAPI 進行用戶身份驗證時遇到了“POST /login HTTP/1.1”422 Unprocessable Entity錯誤。 這個問題是因為我如何從客戶端捕獲身份驗證數據。 我將分享解決方案以及我做錯了什么
from fastapi.security import OAuth2PasswordBearer
from fastapi.security import OAuth2PasswordRequestForm
from fastapi import Depends
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login")
@app.post('/login', response_model=Dict)
def login(
payload: OAuth2PasswordRequestForm = Depends(), # <--- here's all that matters
session: Session = Depends(get_db)
):
### login logic
在我的例子中,我沒有使用OAuth2PasswordRequestForm
,而是使用了一個 UserScheme 來捕獲username
和password
,並在 function 簽名上將其聲明為 Body 參數,即
@app.post('/login', response_model=Dict)
def login(
payload: UserSchema = Body()
....
....
)
以上說法並不完全錯誤。 當我按原樣使用登錄端點時,它確實工作得很好。
在嘗試使用授權按鈕進行身份驗證時,它使用login
端點底層(因為這是作為 tokenUrl 傳遞的),這是我收到無法處理的實體錯誤的時候
希望這可以幫助
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.