10

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?

2 Answers 2

15

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 
Sign up to request clarification or add additional context in comments.

1 Comment

I don't really understand why Body behaves like that by default. Do you have a good example of why they made that the default behaviour?
-3

To get any data from body with FastApi:

@app.post("/someurl") async def someMethod(body: dict): return body 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.