I have a POST FastAPI method. I do not want to construct a class nor query string. So, I decide to apply Body()
method.
@app.post("/test-single-int")
async def test_single_int(
t: int = Body(...)
):
pass
This is the request
POST http://localhost:8000/test-single-int/
{
"t": 10
}
And this is the response
HTTP/1.1 422 Unprocessable Entity
date: Fri, 22 May 2020 10:00:16 GMT
server: uvicorn
content-length: 83
content-type: application/json
connection: close
{
"detail": [
{
"loc": [
"body",
"s"
],
"msg": "str type expected",
"type": "type_error.str"
}
]
}
However, after trying with many samples, I found that they will not error if I have more than one Body()
. For example,
@app.post("/test-multi-mix")
async def test_multi_param(
s: str = Body(...),
t: int = Body(...),
):
pass
Request
POST http://localhost:8000/test-multi-mix/
{
"s": "test",
"t": 10
}
Response
HTTP/1.1 200 OK
date: Fri, 22 May 2020 10:16:12 GMT
server: uvicorn
content-length: 4
content-type: application/json
connection: close
null
Does anyone have any idea about my implementation? Are there wrong? Is it not best practice? Or it is a bug?
It is not a bug, it is how Body behaves, it exists for "extending" request params how documentation outlines:
class Item(BaseModel):
name: str
class User(BaseModel):
username: str
full_name: str = None
@app.put("/items/{item_id}")
async def update_item(
*,
item_id: int,
item: Item,
user: User,
importance: int = Body(..., gt=0),
q: str = None
):
pass
Valid request body for this view would be:
{
"item": {
"name": "Foo",
"tax": 3.2
},
"user": {
"username": "dave",
"full_name": "Dave Grohl"
},
"importance": 5
}
If you really want to use Body alone you must specify embed=True
, this one works as expected:
@app.put("/items/{item_id}")
async def update_item(
*,
item_id:int,
importance: int = Body(..., gt=0, embed=True),
q: str = None
):
pass
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With