FastAPI POST request with List input raises 422 Unprocessable Entity error
Question:
Hi I am newbie in FastAPI and want to write a POST request in which an input parameter is a list, but I got error 422 unprocessable entity:
{
"detail": [
{
"loc": [
"body"
],
"msg": "field required",
"type": "value_error.missing"
}
]
}
my POST request is:
@router.post('',status_code=200)
def register(reg_id: int, reg_name: str, reg_option_list:List[int]):
reg_item = My_DB(
id=reg_id,
name=reg_name,
option_list=reg_option_list,
)
item = db.query(My_DB).filter(My_DB.id == service_id).first()
if item is not None:
raise HTTPException(status_code=400, detail="Item exists.")
db.add(reg_item)
db.commit()
return reg_item
But when I change my code like below, remove list input and set the value in code as a list, everything works fine:
@router.post('',status_code=200)
def register(reg_id: int, reg_name: str,):
reg_item = My_DB(
id=reg_id,
name=reg_name,
option_list=[1,2,3],
)
item = db.query(My_DB).filter(My_DB.id == service_id).first()
if item is not None:
raise HTTPException(status_code=400, detail="Item exists.")
db.add(reg_item)
db.commit()
return reg_item
I will appreciate any help about my list input parameter. Thanks.
Answers:
As per the documentation (have a look at the "Tip" section)
To declare a query parameter with a type of list
, like in the example
above, you need to explicitly use Query
, otherwise it would be
interpreted as a request body
.
Thus, by declaring a List
parameter in the way you do, the endpoint will expect to receive it as body
, rather than query
, parameter. Hence, the 422 unprocessable entity
error with the specific details you provided (i.e., body
field is missing). You could also check that through OpenAPI/Swagger UI at, for instance, http://127.0.0.1:8000/docs
. You would see that the value for reg_option_list
is expected to be passed to the Request body
section.
The way to do this is to define the query parameter explicitly with Query
, allowing thus the parameter to appear multiple times in the URL. Example below:
from fastapi import Query
@router.post('/')
def register(reg_id: int, reg_name: str, reg_option_list: List[int] = Query(...)):
# ...
Sample URL query string:
?reg_id=1®_name=foo®_option_list=1®_option_list=2®_option_list=3
You can use Query in default type
from typing import List
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
def read_items(q: List[int] = Query(None)):
return {"q": q}
Hi I am newbie in FastAPI and want to write a POST request in which an input parameter is a list, but I got error 422 unprocessable entity:
{
"detail": [
{
"loc": [
"body"
],
"msg": "field required",
"type": "value_error.missing"
}
]
}
my POST request is:
@router.post('',status_code=200)
def register(reg_id: int, reg_name: str, reg_option_list:List[int]):
reg_item = My_DB(
id=reg_id,
name=reg_name,
option_list=reg_option_list,
)
item = db.query(My_DB).filter(My_DB.id == service_id).first()
if item is not None:
raise HTTPException(status_code=400, detail="Item exists.")
db.add(reg_item)
db.commit()
return reg_item
But when I change my code like below, remove list input and set the value in code as a list, everything works fine:
@router.post('',status_code=200)
def register(reg_id: int, reg_name: str,):
reg_item = My_DB(
id=reg_id,
name=reg_name,
option_list=[1,2,3],
)
item = db.query(My_DB).filter(My_DB.id == service_id).first()
if item is not None:
raise HTTPException(status_code=400, detail="Item exists.")
db.add(reg_item)
db.commit()
return reg_item
I will appreciate any help about my list input parameter. Thanks.
As per the documentation (have a look at the "Tip" section)
To declare a query parameter with a type of
list
, like in the example
above, you need to explicitly useQuery
, otherwise it would be
interpreted as arequest body
.
Thus, by declaring a List
parameter in the way you do, the endpoint will expect to receive it as body
, rather than query
, parameter. Hence, the 422 unprocessable entity
error with the specific details you provided (i.e., body
field is missing). You could also check that through OpenAPI/Swagger UI at, for instance, http://127.0.0.1:8000/docs
. You would see that the value for reg_option_list
is expected to be passed to the Request body
section.
The way to do this is to define the query parameter explicitly with Query
, allowing thus the parameter to appear multiple times in the URL. Example below:
from fastapi import Query
@router.post('/')
def register(reg_id: int, reg_name: str, reg_option_list: List[int] = Query(...)):
# ...
Sample URL query string:
?reg_id=1®_name=foo®_option_list=1®_option_list=2®_option_list=3
You can use Query in default type
from typing import List
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
def read_items(q: List[int] = Query(None)):
return {"q": q}