如何将 JSON 数据从 JavaScript 前端发布到 FastAPI 后端?

Spy*_*lis 4 python reactjs next.js fastapi

我试图将一个名为“ethAddress”的值从客户端的输入表单传递到 FastAPI,以便我可以在函数中使用它来生成 matplotlib 图表。

我正在使用 fetch 将输入的文本发布到 Charts.tsx 文件中:

   fetch("http://localhost:8000/ethAddress", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(ethAddress),
    }).then(fetchEthAddresses);
Run Code Online (Sandbox Code Playgroud)

然后我的 api.py 文件设置如下:

#imports
app = FastAPI()

@app.get("/ethAddress")
async def get_images(background_tasks: BackgroundTasks, ethAddress: str):
    
    image = EthBalanceTracker.get_transactions(ethAddress)
    img_buf = image
    background_tasks.add_task(img_buf.close)
    headers = {'Content-Disposition': 'inline; filename="out.png"'}
    return Response(img_buf.getvalue(), headers=headers, media_type='image/png')


@app.post("/ethAddress")
async def add_ethAddress(ethAddress: str):
    return ethAddress
Run Code Online (Sandbox Code Playgroud)

据我了解,我使用请求将请求正文中的“ethAddress”从客户端传递到后端fetch POST,然后我可以访问@app.post在 FastAPI 中使用已发布的值。然后我将该值作为字符串返回。然后我在路线中使用它GET来生成图表。

我收到此错误:

INFO:     127.0.0.1:59821 - "POST /ethAddress HTTP/1.1" 422 Unprocessable Entity
INFO:     127.0.0.1:59821 - "GET /ethAddress HTTP/1.1" 422 Unprocessable Entity
Run Code Online (Sandbox Code Playgroud)

我还尝试将客户端上的获取方法切换为 GET 而不是 POST。但出现以下错误:

TypeError: Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body.
Run Code Online (Sandbox Code Playgroud)

Chr*_*ris 5

ethAddress您在端点中定义的方式应作为查询参数;因此,出现422 Unprocessable Entity错误。根据文档

当您声明不属于路径参数一部分的其他函数参数时,它们会自动解释为“查询”参数。

要将参数解释为 JSON,您需要:

选项1

创建 Pydantic 模型

from pydantic import BaseModel

class Item(BaseModel):
    eth_addr: str

@app.post('/ethAddress')
def add_eth_addr(item: Item):
    return item
Run Code Online (Sandbox Code Playgroud)

FastAPI 期望的主体如下:

{
    "eth_addr": "some addr"
}
Run Code Online (Sandbox Code Playgroud)

使用获取 API:

//...
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"eth_addr": "some addr"}),
//...
Run Code Online (Sandbox Code Playgroud)

选项2

或者,使用以下Body类型:

from fastapi import Body

@app.post('/ethAddress')
def add_eth_addr(eth_addr: str = Body()):
    return {'eth_addr': eth_addr}
Run Code Online (Sandbox Code Playgroud)

FastAPI 期望的主体如下:

"some addr"
Run Code Online (Sandbox Code Playgroud)

使用获取 API:

//...
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify("some addr"),
//...
Run Code Online (Sandbox Code Playgroud)

选项3

由于您只有一个主体参数,因此您可能需要使用特殊Body参数embed

from fastapi import Body

@app.post('/ethAddress')
def add_eth_addr(eth_addr: str = Body(embed=True)):
    return {'eth_addr': eth_addr}
Run Code Online (Sandbox Code Playgroud)

FastAPI 期望的主体如下:

{
    "eth_addr": "some addr"
}
Run Code Online (Sandbox Code Playgroud)

使用获取 API:

//...
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"eth_addr": "some addr"}),
//...
Run Code Online (Sandbox Code Playgroud)

相关答案,包括有关如何发布 JSON 数据的 JavaScript 示例,可以在此处此处以及此处此处找到。