I would like 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 under 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 in the request body
, rather than in the query string as a query
parameter. Hence, a 422 unprocessable entity
error is raised, including the specific details you provided (i.e., body
field is missing). You could also confirm that through OpenAPI/Swagger UI at /docs
, 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, not in the query parameters.
List
of data in the query stringThe way to do this is to define the query parameter explicitly with Query
; thus, allowing the parameter to appear multiple times in the URL. Since such a request would not include a request body, you should rather use a GET
request, which is used when one requests data from the server, whereas POST
is used to send data to the server stored in the request body.
from fastapi import FastAPI, Query
from typing import List
app = FastAPI()
@app.get('/')
def register(reg_id: int, reg_name: str, reg_options: List[int] = Query(...)):
return reg_options
Test URL with Query
parameters List
:
http://127.0.0.1:8000/?reg_id=1®_name=foo®_options=1®_options=2®_options=3
Test using Python requests:
import requests
url = 'http://127.0.0.1:8000/?reg_id=1®_name=foo®_options=1®_options=2®_options=3'
r = requests.get(url)
print(r.text)
or, preferably:
import requests
url = 'http://127.0.0.1:8000/'
params = {'reg_id': 1, 'reg_name': 'foo', 'reg_options': [1, 2, 3]}
r = requests.get(url, params=params)
print(r.text)
List
of data in the request bodyIf you would like to use a POST
request and send the data in the request body instead, you could simply define the reg_options
parameter above in the same way, but without using the = Query(...)
part. This should tell FastAPI to expect a list of data for that endpoint in the body of the request. For more details and examples on how to send data in the request body to a FastAPI backend, please have a look here, as well as here and here. Further related answers can be found here, here, as well as here and here.