我一直在使用FastAPI创建基于HTTP的API。目前,它支持JSON编码的参数,但我还希望支持在同一URL下的form-urlencoded
(最好甚至是form-data
)参数。
根据Nikita的回答,我可以通过以下方式使不同的URL起作用:
from typing import Optional
from fastapi import FastAPI, Body, Form, Depends
from pydantic import BaseModel
class MyItem(BaseModel):
id: Optional[int] = None
txt: str
@classmethod
def as_form(cls, id: Optional[int] = Form(None), txt: str = Form(...)) -> 'MyItem':
return cls(id=id, txt=txt)
app = FastAPI()
@app.post("/form")
async def form_endpoint(item: MyItem = Depends(MyItem.as_form)):
print("got item =", repr(item))
return "ok"
@app.post("/json")
async def json_endpoint(item: MyItem = Body(...)):
print("got item =", repr(item))
return "ok"
我可以使用curl
进行测试,方法如下:
curl -X POST "http://localhost:8000/form" -d 'txt=test'
并且
curl -sS -X POST "http://localhost:8000/json" -H "Content-Type: application/json" -d '{"txt":"test"}'
似乎有一个单一的 URL 能够接受两种内容类型并将模型适当地解析会更好。但是以上代码目前无论使用何种方式都会失败:
{"detail":[{"loc":["body","txt"],"msg":"field required","type":"value_error.missing"}]}
或者
{"detail":"There was an error parsing the body"}
如果我将表单编码发布到错误的端点,例如
/json
。为了得到额外的加分,我还想支持form-data
编码参数,因为它似乎相关(我的txt
在实践中可能会变得非常长),但如果它足够不同,可能需要另外提问。