тело fastapi ведет себя по-разному между двумя функциями

#python #fastapi

Вопрос:

У меня есть две функции, и я использую похожие параметры, но для одной они работают так, как ожидалось, а для другой-нет:

 from fastapi import FastAPI, Header, HTTPException, Body

@app.post("/portfolio/analytics/carbon-footprint", dependencies=[Depends(api_counter)])
async def getPortfolioCarbonFootprint(
    tickers: list = Body(...),
    func: str = Body(...),
    http_client: aiohttp.ClientSession = fastapi.Depends(http_client)
):
  
    print(tickers)
    return res

#historical prices
@app.post("/portfolio/analytics/historicalprices", dependencies=[Depends(api_counter)])
async def getPortfolioHistoricalPrices(
    tickers: list = Body(...),
    http_client: aiohttp.ClientSession = fastapi.Depends(http_client)
):
  
    print(tickers)
    jsonResults = await getHistoricalPrices(tickers)
    return jsonResults
 

Для обоих я отправляю ему этот json:

 {"tickers" : [ "IBM.US", "MSFT.US"]}
 

первая функция работает идеально. Второй возвращает эту ошибку:

 {
    "detail": [
        {
            "loc": [
                "body"
            ],
            "msg": "value is not a valid list",
            "type": "type_error.list"
        }
    ]
}
 

Вот тут-то все и становится странным. Если я отправлю это:

 [ "IBM.US", "MSFT.US"]
 

тогда все работает так, как и ожидалось.

Так что функция 1 работает нормально. Функция 2 копируется из функции 1, и она не принимает тикеры в качестве входных данных, но отправка ей необработанного списка работает.

Ответ №1:

Разница между этими двумя функциями заключается в количестве параметров, которые должен заполнить пользователь. В первой функции у вас есть tickers и func , а во второй у вас есть только tickers .

Из документации FastAPI:

Но если у вас есть только один параметр тела элемента из элемента модели Pydantic.

По умолчанию FastAPI будет ожидать своего тела напрямую.

Но если вы хотите, чтобы он ожидал JSON с ключевым элементом и содержимым модели внутри него, вы можете использовать специальный параметр Body.

Поэтому во второй функции, если вы хотите иметь ключ, вы должны написать:

 tickers: list = Body(..., embed=True)