在 FastAPI 中自动生成列表查询参数的 API 文档

问题描述 投票:0回答:1

FastAPI 不会为具有数组查询参数的查询生成文档。即:

GET /items?filter[name]=foo&filter[category]=bar&sort=-id,name
。 根据 Openapi 3.0 文档,它们支持
deepObject
查询参数 (
/users?id[role]=admin&id[firstName]=Alex
)。但是如何使用 FastAPI 来做到这一点呢?

架构:

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]

路线:

@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))

文档页面:

如果可能的话,我希望在文档中看到一个

filter
参数,其中包含方括号之间的归档名称及其值的输入。

更新:

我现在看到的唯一解决方案是手动扩展 openapi 架构:

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

仍然不知道如何自动生成,所以停止使用此解决方案:

@router.get('', response_model=Page[ItemOut], openapi_extra={
'parameters': [
    {
        'in': 'query',
        'name': 'filter[name]',
        'required': False,
        'schema': {
            'minLength': 1,
            'type': 'string',
            'example': 'foobar'
        }
    },
    ...
python-3.x swagger-ui fastapi openapi pydantic
1个回答
0
投票

遇到同样的问题,只找到一种解决方案。如果 GET 中的数组参数直接作为 kwarg 传递(如 this 文档中所示),Fastapi 会自动生成数组输入。但我不喜欢这种方式,因为它对应用程序架构非常不利,因为我想在单独的模块中控制查询参数。我也无法像这样输入参数:

from typing_extensions import Unpack

async def my_view(**filter_kwargs: Unpack[MyTypedDict]): ...

因为fastapi无法解析。因此,目前覆盖 openapi 设置是避免视图中出现大量参数的最佳方法。

更新!解决方案:

抱歉信息有误,我在20分钟后才解决:

class Filters(BaseModel):
string_array: list[str] = Field(Query())

@router.get("/test")
async def test(
    filter_kwargs: Filters = Depends(),
):
    return {"filter_kwargs": filter_kwargs.string_array}

© www.soinside.com 2019 - 2024. All rights reserved.