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.