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

问题描述 投票:0回答:1

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

我正在使用 fetch 来 POST Charts.tsx 文件中输入的文本:

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

然后我的 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

据我了解,我使用

fetch
POST
请求将请求正文中的“ethAddress”从客户端传递到后端,然后我可以访问在 FastAPI 中使用
@app.post
发布的值。然后我将该值作为字符串返回。然后我在
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

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

TypeError: Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body.
python reactjs next.js fastapi
1个回答
8
投票

您在端点中定义

ethAddress
的方式应作为查询参数;因此,出现
422 Unprocessable Entity
错误。根据文档

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

要将参数解释为 JSON,您需要使用以下选项之一。

选项1

创建Pydantic模型

from pydantic import BaseModel


class Item(BaseModel):
    eth_addr: str


@app.post('/')
async def add_eth_addr(item: Item):
    return item

FastAPI 期望的主体如下:

{
    "eth_addr": "some addr"
}

使用 Fetch API 执行 HTTP 请求:

fetch('/', {
      method: 'POST',
      headers: {
         'Accept': 'application/json',
         'Content-Type': 'application/json'
      },
      body: JSON.stringify({
         "eth_addr": "some addr"
      }),
   })
   .then(resp => resp.json()) // or, resp.text(), etc.
   .then(data => {
      console.log(data); // handle response data
   })
   .catch(error => {
      console.error(error);
   });

选项2

使用

Body
参数类型:

from fastapi import Body


@app.post('/')
async def add_eth_addr(eth_addr: str = Body()):
    return {'eth_addr': eth_addr}

FastAPI 期望的主体如下:

"some addr"

使用 Fetch API 执行 HTTP 请求:

fetch('/', {
      method: 'POST',
      headers: {
         'Accept': 'application/json',
         'Content-Type': 'application/json'
      },
      body: JSON.stringify("some addr"),
   })
   .then(resp => resp.json()) // or, resp.text(), etc.
   .then(data => {
      console.log(data); // handle response data
   })
   .catch(error => {
      console.error(error);
   });

选项3

由于您有一个单个主体参数,您可能需要使用特殊的

Body
参数
embed

from fastapi import Body


@app.post('/')
async def add_eth_addr(eth_addr: str = Body(embed=True)):
    return {'eth_addr': eth_addr}

FastAPI 期望的主体如下:

{
    "eth_addr": "some addr"
}

使用 Fetch API 执行 HTTP 请求:

fetch('/', {
      method: 'POST',
      headers: {
         'Accept': 'application/json',
         'Content-Type': 'application/json'
      },
      body: JSON.stringify({
         "eth_addr": "some addr"
      }),
   })
   .then(resp => resp.json()) // or, resp.text(), etc.
   .then(data => {
      console.log(data); // handle response data
   })
   .catch(error => {
      console.error(error);
   });

相关答案,包括如何发布 JSON 数据的 JavaScript 示例,可以在 herehereherehere 找到。当涉及到在同一请求中发布 JSON 数据和文件时,这个答案也可能会有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.