FastAPI does not generate docs for queries that have array query parameters. I.e: GET /items?filter[name]=foo&filter[category]=bar&sort=-id,name.
According to Openapi 3.0 docs they support a deepObject query parameters (/users?id[role]=admin&id[firstName]=Alex). But how to do this with FastAPI?
Schema:
import re
from typing import Sequence, Generic, TypeVar, Dict, List, Optional, Any
from urllib.parse import unquote
from pydantic import BaseModel
from fastapi import Query, Request
class ListQueryParams(BaseModel):
query: str = Query(None, description="Search query", example='heart', min_length=1)
sort: List[str] = Query(None, description="Sorting", example='-id', min_length=2)
filter: Optional[Dict[str, Any]] = Query(dict(), description="Filters")
def __init__(self, request: Request, **data: Any):
super().__init__(**data)
self._set_filter(request)
self._set_sort(request)
def _set_filter(self, request: Request):
unquoted_params = unquote(str(request.query_params))
filters = re.findall(r'filter\[([a-z0-9-_]{2,})]', unquoted_params, re.IGNORECASE)
for key in filters:
value = request.query_params.get(f'filter[{key}]')
self.filter[key] = value
def _set_sort(self, request: Request):
self.sort = [field.strip() for field in request.query_params.get('sort', '').split(',') if field]
Route:
@router.get('', response_model=Page[ItemOut])
def list_items(params: ListQueryParams = Depends(), db: Session = Depends(get_db)):
return paginate(ItemsManager(db).get_items_list_query(query=params.query, filter=params.filter, sort=params.sort))
Docs page:
I would like to see a filter parameter with inputs for filed names between square braces and their values as a result in the docs if it is possible.
UPD:
The only solution I see now is to extend the openapi schema manually:
from fastapi.openapi.utils import get_openapi
openapi_schema = get_openapi(...)
paths = openapi_schema['paths']
for path in paths:
for method in paths[path]:
if paths[path][method]['operationId'] == 'list_items_v1_items_get':
paths[path][method]['parameters'].extend([
{
'in': 'query',
'name': 'filter[name]',
'required': False
},
...
UPD
Still don't know how to autogenerate, so stopped with this solution:
@router.get('', response_model=Page[ItemOut], openapi_extra={
'parameters': [
{
'in': 'query',
'name': 'filter[name]',
'required': False,
'schema': {
'minLength': 1,
'type': 'string',
'example': 'foobar'
}
},
...
