'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