1

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.

Chris
  • 18,724
  • 6
  • 46
  • 80
Saha
  • 339
  • 2
  • 16

2 Answers2

0

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 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.

The 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.

Example

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

Sample URL with Query parameter List:

http://127.0.0.1:8000/?reg_id=1&reg_name=foo&reg_options=1&reg_options=2&reg_options=3

Test using Python requests:

import requests

url = 'http://127.0.0.1:8000/?reg_id=1&reg_name=foo&reg_options=1&reg_options=2&reg_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)

If you would like to use a POST request and send the data in the request body instead, then simply define the parameter without using the = Query(...) part, and have a look here, as well as here and here on how to send data in the request body to FastAPI backend. Further related answers can be found here, here, as well as here and here.

Chris
  • 18,724
  • 6
  • 46
  • 80
  • thanks for your answer, I tried this as documentation but got error 500 and "invalid input syntax for type integer" – Saha Mar 10 '22 at 16:38
  • I used ```option_list = {"option": reg_option_list}``` and it is about the option value with this details ```invalid input syntax for type integer: "option"``` – Saha Mar 10 '22 at 16:45
  • 1
    I edited it to : option_list =[reg_option_list] and it works perfectly. – Saha Mar 10 '22 at 17:00
0

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}
maral7495
  • 1
  • 2
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 07 '23 at 16:08