Перейти к содержанию

Возврат ответа напрямую

Когда вы создаёте FastAPI операцию пути, вы можете возвращать из неё любые данные: dict, list, Pydantic-модель, модель базы данных и т.д.

По умолчанию FastAPI автоматически преобразует возвращаемое значение в JSON с помощью jsonable_encoder, как описано в JSON кодировщик.

Затем "под капотом" эти данные, совместимые с JSON (например dict), помещаются в JSONResponse, который используется для отправки ответа клиенту.

Но вы можете возвращать JSONResponse напрямую из ваших операций пути.

Это может быть полезно, например, если нужно вернуть пользовательские HTTP-заголовки или cookie.

Возврат Response

На самом деле, вы можете возвращать любой объект Response или его подкласс.

Подсказка

JSONResponse сам по себе является подклассом Response.

И когда вы возвращаете Response, FastAPI передаст его напрямую.

Это не приведет к преобразованию данных с помощью Pydantic-моделей, содержимое не будет преобразовано в какой-либо тип и т.д.

Это даёт вам большую гибкость. Вы можете возвращать любые типы данных, переопределять любые объявления или валидацию данных и т.д.

Использование jsonable_encoder в Response

Поскольку FastAPI не изменяет объект Response, который вы возвращаете, вы должны убедиться, что его содержимое готово к отправке.

Например, вы не можете поместить Pydantic-модель в JSONResponse, не преобразовав её сначала в dict с помощью преобразования всех типов данных (таких как datetime, UUID и т.д.) в совместимые с JSON типы.

В таких случаях вы можете использовать jsonable_encoder для преобразования данных перед передачей их в ответ:

from datetime import datetime
from typing import Union

from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from fastapi.responses import JSONResponse
from pydantic import BaseModel


class Item(BaseModel):
    title: str
    timestamp: datetime
    description: Union[str, None] = None


app = FastAPI()


@app.put("/items/{id}")
def update_item(id: str, item: Item):
    json_compatible_item_data = jsonable_encoder(item)
    return JSONResponse(content=json_compatible_item_data)

Технические детали

Вы также можете использовать from starlette.responses import JSONResponse.

FastAPI предоставляет starlette.responses через fastapi.responses просто для вашего удобства, как разработчика. Но большинство доступных Response-классов поступают напрямую из Starlette.

Возврат пользовательского Response

Пример выше показывает все необходимые части, но он пока не очень полезен, так как вы могли бы просто вернуть item напрямую, и FastAPI поместил бы его в JSONResponse, преобразовав в dict и т.д. Всё это происходит по умолчанию.

Теперь давайте посмотрим, как можно использовать это для возврата пользовательского ответа.

Допустим, вы хотите вернуть ответ в формате XML.

Вы можете поместить ваш XML-контент в строку, поместить её в Response и вернуть:

from fastapi import FastAPI, Response

app = FastAPI()


@app.get("/legacy/")
def get_legacy_data():
    data = """<?xml version="1.0"?>
    <shampoo>
    <Header>
        Apply shampoo here.
    </Header>
    <Body>
        You'll have to use soap here.
    </Body>
    </shampoo>
    """
    return Response(content=data, media_type="application/xml")

Примечания

Когда вы возвращаете объект Response напрямую, его данные не валидируются, не преобразуются (не сериализуются) и не документируются автоматически.

Но вы всё равно можете задокументировать это, как описано в Дополнительные ответы в OpenAPI.

В следующих разделах вы увидите, как использовать/объявлять такие кастомные Response, при этом сохраняя автоматическое преобразование данных, документацию и т.д.