如何在FastAPI中POST一个只有一个主体参数的JSON?

4

我有一个名为main.py的文件,其中我使用了一个只包含一个输入参数(整数)的POST调用。以下是简化后的代码:

from fastapi import FastAPI

app = FastAPI()

@app.post("/do_something/")
async def do_something(process_id: int):
    # some code
    return {"process_id": process_id}

现在,如果我运行保存在文件test_main.py中的测试代码,即:
from fastapi.testclient import TestClient
from main import app

client = TestClient(app)

def test_do_something():
    response = client.post(
        "/do_something/",
        json={
            "process_id": 16
        }
    )
    return response.json()

print(test_do_something())

我理解为:

{'detail': [{'loc': ['query', 'process_id'], 'msg': 'field required', 'type': 'value_error.missing'}]}

我无法弄清楚错误在哪里。必须保持调用方式为POST

1个回答

6
错误基本上是指,缺少所需的查询参数process_id。原因是您发送了带有请求body,即JSON有效载荷的POST请求;但是,您的端点却期望一个查询参数。要以JSON格式接收数据,需要创建Pydantic BaseModel,如下所示,并以与客户端已经执行的方式发送数据。
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Item(BaseModel):
    process_id: int
    
@app.post("/do_something")
def do_something(item: Item):
    return item

但是,如果需要传递查询参数,则可以按照与之前相同的方式创建端点,但在客户端上,您需要将参数添加到URL本身中,如文档所述,如下所示:

def test_do_something():
    response = client.post("/do_something?process_id=16")
    return response.json()

更新

或者,您可以使用Body(..., embed=True)传递单个body参数,如下所示(有关发布JSON数据的更多详细信息和选项,请参见this answerthis answer):

@app.post("/do_something")
def do_something(process_id: int = Body(..., embed=True)):
    return process_id

有没有可能在不创建 Pydantic 模型的情况下完成这个操作?通常,如果我有多个参数,我会在定义中使用 async def do_something_else(items: List[Dict], process_id: int = Body(...)),并在调用时使用 client.post("/do_something_else/", json={"process_id": ..., "items": [{...}, {...}]}) - LJG
1
但是如果我只有一个数字参数,就像我问题中的示例一样,Body(...)将不起作用。 - LJG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接