Ir para o conteúdo

Retornando uma Resposta Diretamente

Quando você cria uma operação de rota no FastAPI você pode retornar qualquer dado nela: um dicionário (dict), uma lista (list), um modelo do Pydantic ou do seu banco de dados, etc.

Por padrão, o FastAPI irá converter automaticamente o valor do retorno para JSON utilizando o jsonable_encoder explicado em JSON Compatible Encoder.

Então, por baixo dos panos, ele incluiria esses dados compatíveis com JSON (e.g. um dict) dentro de uma JSONResponse que é utilizada para enviar uma resposta para o cliente.

Mas você pode retornar a JSONResponse diretamente nas suas operações de rota.

Pode ser útil para retornar cabeçalhos e cookies personalizados, por exemplo.

Retornando uma Response

Na verdade, você pode retornar qualquer Response ou subclasse dela.

Dica

A própria JSONResponse é uma subclasse de Response.

E quando você retorna uma Response, o FastAPI vai repassá-la diretamente.

Ele não vai fazer conversões de dados com modelos do Pydantic, não irá converter a tipagem de nenhum conteúdo, etc.

Isso te dá bastante flexibilidade. Você pode retornar qualquer tipo de dado, sobrescrever qualquer declaração e validação nos dados, etc.

Utilizando o jsonable_encoder em uma Response

Como o FastAPI não realiza nenhuma mudança na Response que você retorna, você precisa garantir que o conteúdo dela está pronto para uso.

Por exemplo, você não pode colocar um modelo do Pydantic em uma JSONResponse sem antes convertê-lo em um dict com todos os tipos de dados (como datetime, UUID, etc) convertidos para tipos compatíveis com JSON.

Para esses casos, você pode usar o jsonable_encoder para converter seus dados antes de repassá-los para a resposta:

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)

Detalhes Técnicos

Você também pode utilizar from starlette.responses import JSONResponse.

FastAPI utiliza a mesma starlette.responses como fastapi.responses apenas como uma conveniência para você, desenvolvedor. Mas maior parte das respostas disponíveis vem diretamente do Starlette.

Retornando uma Response

O exemplo acima mostra todas as partes que você precisa, mas ainda não é muito útil, já que você poderia ter retornado o item diretamente, e o FastAPI colocaria em uma JSONResponse para você, convertendo em um dict, etc. Tudo isso por padrão.

Agora, vamos ver como você pode usar isso para retornar uma resposta personalizada.

Vamos dizer quer retornar uma resposta XML.

Você pode colocar o seu conteúdo XML em uma string, colocar em uma Response, e retorná-lo:

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

Notas

Quando você retorna uma Response diretamente os dados não são validados, convertidos (serializados) ou documentados automaticamente.

Mas você ainda pode documentar como descrito em Retornos Adicionais no OpenAPI .

Você pode ver nas próximas seções como usar/declarar essas Responses customizadas enquanto mantém a conversão e documentação automática dos dados.