Ir para o conteúdo

Retornando uma Resposta Diretamente

Quando você cria uma operação de rota no ReadyAPI 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 ReadyAPI 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 ReadyAPI 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 ReadyAPI 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 pydantic import BaseModel
from readyapi import ReadyAPI
from readyapi.encoders import jsonable_encoder
from readyapi.responses import JSONResponse


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


app = ReadyAPI()


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

ReadyAPI utiliza a mesma starlette.responses como readyapi.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 ReadyAPI 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 readyapi import ReadyAPI, Response

app = ReadyAPI()


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