'FastAPI - GET Request with Pydantic List field
I'm new to FastAPI (migrating from Flask) and I'm trying to create a Pydantic model for my GET
route:
from fastapi import APIRouter,Depends
from pydantic import BaseModel
from typing import Optional,List
router = APIRouter()
class SortModel(BaseModel):
field: Optional[str]
directions: List[str]
@router.get("/pydanticmodel")
def get_sort(criteria: SortModel = Depends(SortModel)):
pass #my code for handling this route.....
When I'm running curl -X GET http://localhost:XXXX/pydanticmodel?directions=up&directions=asc&field=id
I'm getting 422 Unprocessable Entity: {"detail":[{"loc":["body"],"msg":"field required","type":"value_error.missing"}]}
But if I'm changing directions:List[str]
-> directions: str
I'm getting 200 OK
with directions="asc"
.
What is the reason that str
works for query param and List[str]
does not? What am I doing wrong?
Thanks.
Solution 1:[1]
It is not, as yet, possible to use a GET Request with Pydantic List field as query parameter. Once you declare a List field in the model, it is expected being body parameter instead of query one (you can check that through OpenAPI at http://127.0.0.1:8000/docs, for instance). Additionally, as you are using a GET request method, even if you add the list of directions
in the body and try sending the request, it won't work; since a POST request would be required for that operation.
The way to do this is to implement your query parameter parsing in a separate class dependency, as described here. Remember to define the List field with Query
, so that directions
can appear multiple times in the URL, or in others words, to receive multiple values.
from typing import List, Optional
from fastapi import APIRouter, Depends, Query
router = APIRouter()
class SortModel:
def __init__(
self,
field: Optional[str],
directions: List[str] = Query(...)
):
self.field = field
self.directions = directions
@router.get("/")
def send_user(criteria: SortModel = Depends(SortModel)):
return criteria
Solution 2:[2]
I'm running into the same issue. The following solution will work, but it isn't really what I want however maybe it's good enough for you:
from fastapi import APIRouter,Depends, Query
from pydantic import BaseModel
from typing import Optional,List
router = APIRouter()
class SortModel(BaseModel):
field: Optional[str]
@router.get("/pydanticmodel")
def get_sort(criteria: SortModel = Depends(SortModel), directions: List[str] = Query(...)):
pass #my code for handling this route.....
Solution 3:[3]
It's not a Pydantic or FastAPI problem.
If you want to send an array with curl you should use -d flag.
In: curl -X GET "http://127.0.0.1:8000/pydanticmodel?field=123" -d "[\"string\"]"
Out: {"field":"123","directions":["string"]}
Now your code should work perfectly.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Jon E |
Solution 3 | Yagiz Degirmenci |