How to POST a JSON having a single body parameter in FastAPI?
Question:
I have a file called main.py
in which I put a POST
call with only one input parameter (integer). Simplified code is given below:
from fastapi import FastAPI
app = FastAPI()
@app.post("/do_something/")
async def do_something(process_id: int):
# some code
return {"process_id": process_id}
Now, if I run the code for the test, saved in the file test_main.py
, that is:
from fastapi.testclient import TestClient
from main import app
client = TestClient(app)
def test_do_something():
response = client.post(
"/do_something/",
json={
"process_id": 16
}
)
return response.json()
print(test_do_something())
I get:
{'detail': [{'loc': ['query', 'process_id'], 'msg': 'field required', 'type': 'value_error.missing'}]}
I can’t figure out what the mistake is. It is necessary that it remains a POST
call.
Answers:
The error basically says that, the required query parameter process_id
is missing. The reason is that you send a POST request with request body
, i.e., JSON payload; however, your endpoint expects a query parameter. To receive the data in JSON format, one needs to create a Pydantic BaseModel—as shown below—and send the data from the client in the same way you already do.
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
process_id: int
@app.post("/do_something")
def do_something(item: Item):
return item
If, however, you need to pass a query parameter, then you create an endpoint in the same way you did, but on client side, you need to add the parameter to the URL itself, as described in the documentation and as shown below:
def test_do_something():
response = client.post("/do_something?process_id=16")
return response.json()
Update
Alternatively, you can pass a single body parameter using Body(..., embed=True)
, as shown below (for more details and options on how to post JSON data, see this answer and this answer):
@app.post("/do_something")
def do_something(process_id: int = Body(..., embed=True)):
return process_id
I have a file called main.py
in which I put a POST
call with only one input parameter (integer). Simplified code is given below:
from fastapi import FastAPI
app = FastAPI()
@app.post("/do_something/")
async def do_something(process_id: int):
# some code
return {"process_id": process_id}
Now, if I run the code for the test, saved in the file test_main.py
, that is:
from fastapi.testclient import TestClient
from main import app
client = TestClient(app)
def test_do_something():
response = client.post(
"/do_something/",
json={
"process_id": 16
}
)
return response.json()
print(test_do_something())
I get:
{'detail': [{'loc': ['query', 'process_id'], 'msg': 'field required', 'type': 'value_error.missing'}]}
I can’t figure out what the mistake is. It is necessary that it remains a POST
call.
The error basically says that, the required query parameter process_id
is missing. The reason is that you send a POST request with request body
, i.e., JSON payload; however, your endpoint expects a query parameter. To receive the data in JSON format, one needs to create a Pydantic BaseModel—as shown below—and send the data from the client in the same way you already do.
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
process_id: int
@app.post("/do_something")
def do_something(item: Item):
return item
If, however, you need to pass a query parameter, then you create an endpoint in the same way you did, but on client side, you need to add the parameter to the URL itself, as described in the documentation and as shown below:
def test_do_something():
response = client.post("/do_something?process_id=16")
return response.json()
Update
Alternatively, you can pass a single body parameter using Body(..., embed=True)
, as shown below (for more details and options on how to post JSON data, see this answer and this answer):
@app.post("/do_something")
def do_something(process_id: int = Body(..., embed=True)):
return process_id