Ir para o conteúdo

Retornando uma Resposta Diretamente

🌐 Tradução por IA e humanos

Esta tradução foi feita por IA orientada por humanos. 🤝

Ela pode conter erros de interpretação do significado original ou soar pouco natural, etc. 🤖

Você pode melhorar esta tradução ajudando-nos a orientar melhor o LLM de IA.

Versão em inglês

Quando você cria uma operação de rota no FastAPI, normalmente você pode retornar qualquer dado: um dict, uma list, um modelo do Pydantic, um modelo do banco de dados, etc.

Se você declarar um Modelo de resposta, o FastAPI irá usá-lo para serializar os dados para JSON, usando o Pydantic.

Se você não declarar um modelo de resposta, o FastAPI usará o jsonable_encoder explicado em Codificador Compatível com JSON e o colocará em uma JSONResponse.

Você também pode criar uma JSONResponse diretamente e retorná-la.

Dica

Normalmente você terá um desempenho muito melhor usando um Modelo de resposta do que retornando uma JSONResponse diretamente, pois assim ele serializa os dados usando o Pydantic, em Rust.

Retornando uma Response

Você pode retornar uma Response ou qualquer subclasse dela.

Informação

A própria JSONResponse é uma subclasse de Response.

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

Ele não fará conversões de dados com modelos do Pydantic, não converterá o conteúdo para nenhum tipo, etc.

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

Isso também te dá muita responsabilidade. Você precisa garantir que os dados retornados estão corretos, no formato correto, que podem ser serializados, 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 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: 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 personalizada

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 que você 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")

Como funciona um Modelo de resposta

Quando você declara um Modelo de resposta - Tipo de retorno em uma operação de rota, o FastAPI irá usá-lo para serializar os dados para JSON, usando o Pydantic.

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None
    tags: list[str] = []


@app.post("/items/")
async def create_item(item: Item) -> Item:
    return item


@app.get("/items/")
async def read_items() -> list[Item]:
    return [
        Item(name="Portal Gun", price=42.0),
        Item(name="Plumbus", price=32.0),
    ]

Como isso acontece no lado do Rust, o desempenho será muito melhor do que se fosse feito com Python comum e a classe JSONResponse.

Ao usar um response_model ou tipo de retorno, o FastAPI não usará o jsonable_encoder para converter os dados (o que seria mais lento) nem a classe JSONResponse.

Em vez disso, ele pega os bytes JSON gerados com o Pydantic usando o modelo de resposta (ou tipo de retorno) e retorna uma Response com o media type correto para JSON diretamente (application/json).

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 Respostas 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.