Se você está começando com o FastAPI, provavelmente você não precisa disso.
Você pode declarar retornos adicionais, com códigos de status adicionais, media types, descrições, etc.
Essas respostas adicionais serão incluídas no esquema do OpenAPI, e também aparecerão na documentação da API.
Porém para as respostas adicionais, você deve garantir que está retornando um Response como por exemplo o JSONResponse diretamente, junto com o código de status e o conteúdo.
Você pode fornecer o parâmetro responses aos seus decoradores de caminho.
Este parâmetro recebe um dict, as chaves são os códigos de status para cada retorno, como por exemplo 200, e os valores são um outro dict com a informação de cada um deles.
Cada um desses dict de retorno pode ter uma chave model, contendo um modelo do Pydantic, assim como o response_model.
O FastAPI pegará este modelo, gerará o esquema JSON dele e incluirá no local correto do OpenAPI.
Por exemplo, para declarar um outro retorno com o status code 404 e um modelo do Pydantic chamado Message, você pode escrever:
fromfastapiimportFastAPIfromfastapi.responsesimportJSONResponsefrompydanticimportBaseModelclassItem(BaseModel):id:strvalue:strclassMessage(BaseModel):message:strapp=FastAPI()@app.get("/items/{item_id}",response_model=Item,responses={404:{"model":Message}})asyncdefread_item(item_id:str):ifitem_id=="foo":return{"id":"foo","value":"there goes my hero"}returnJSONResponse(status_code=404,content={"message":"Item not found"})
Nota
Lembre-se que você deve retornar o JSONResponse diretamente.
Informação
A chave model não é parte do OpenAPI.
O FastAPI pegará o modelo do Pydantic, gerará o JSON Schema, e adicionará no local correto.
O local correto é:
Na chave content, que tem como valor um outro objeto JSON (dict) que contém:
Uma chave com o media type, como por exemplo application/json, que contém como valor um outro objeto JSON, contendo::
Uma chave schema, que contém como valor o JSON Schema do modelo, sendo este o local correto.
O FastAPI adiciona aqui a referência dos esquemas JSON globais que estão localizados em outro lugar, ao invés de incluí-lo diretamente. Deste modo, outras aplicações e clientes podem utilizar estes esquemas JSON diretamente, fornecer melhores ferramentas de geração de código, etc.
O retorno gerado no OpenAI para esta operação de caminho será:
Você pode utilizar o mesmo parâmetro responses para adicionar diferentes media types para o mesmo retorno principal.
Por exemplo, você pode adicionar um media type adicional de image/png, declarando que a sua operação de caminho pode retornar um objeto JSON (com o media type application/json) ou uma imagem PNG:
fromtypingimportUnionfromfastapiimportFastAPIfromfastapi.responsesimportFileResponsefrompydanticimportBaseModelclassItem(BaseModel):id:strvalue:strapp=FastAPI()@app.get("/items/{item_id}",response_model=Item,responses={200:{"content":{"image/png":{}},"description":"Return the JSON item or an image.",}},)asyncdefread_item(item_id:str,img:Union[bool,None]=None):ifimg:returnFileResponse("image.png",media_type="image/png")else:return{"id":"foo","value":"there goes my hero"}
Nota
Note que você deve retornar a imagem utilizando um FileResponse diretamente.
Informação
A menos que você especifique um media type diferente explicitamente em seu parâmetro responses, o FastAPI assumirá que o retorno possui o mesmo media type contido na classe principal de retorno (padrão application/json).
Porém se você especificou uma classe de retorno com o valor None como media type, o FastAPI utilizará application/json para qualquer retorno adicional que possui um modelo associado.
Você também pode combinar informações de diferentes lugares, incluindo os parâmetros response_model, status_code, e responses.
Você pode declarar um response_model, utilizando o código de status padrão 200 (ou um customizado caso você precise), e depois adicionar informações adicionais para esse mesmo retorno em responses, diretamente no esquema OpenAPI.
O FastAPI manterá as informações adicionais do responses, e combinará com o esquema JSON do seu modelo.
Por exemplo, você pode declarar um retorno com o código de status 404 que utiliza um modelo do Pydantic que possui um description customizado.
E um retorno com o código de status 200 que utiliza o seu response_model, porém inclui um example customizado:
fromfastapiimportFastAPIfromfastapi.responsesimportJSONResponsefrompydanticimportBaseModelclassItem(BaseModel):id:strvalue:strclassMessage(BaseModel):message:strapp=FastAPI()@app.get("/items/{item_id}",response_model=Item,responses={404:{"model":Message,"description":"The item was not found"},200:{"description":"Item requested by ID","content":{"application/json":{"example":{"id":"bar","value":"The bar tenders"}}},},},)asyncdefread_item(item_id:str):ifitem_id=="foo":return{"id":"foo","value":"there goes my hero"}else:returnJSONResponse(status_code=404,content={"message":"Item not found"})
Isso será combinado e incluído em seu OpenAPI, e disponibilizado na documentação da sua API:
Você pode querer possuir alguns retornos predefinidos que são aplicados para diversas operações de caminho, porém você deseja combinar com retornos personalizados que são necessários para cada operação de caminho.
Para estes casos, você pode utilizar a técnica do Python de "desempacotamento" de um dict utilizando **dict_to_unpack:
old_dict={"old key":"old value","second old key":"second old value",}new_dict={**old_dict,"new key":"new value"}
Aqui, o new_dict terá todos os pares de chave-valor do old_dict mais o novo par de chave-valor:
{"old key":"old value","second old key":"second old value","new key":"new value",}
Você pode utilizar essa técnica para reutilizar alguns retornos predefinidos nas suas operações de caminho e combiná-las com personalizações adicionais.
Por exemplo:
fromtypingimportUnionfromfastapiimportFastAPIfromfastapi.responsesimportFileResponsefrompydanticimportBaseModelclassItem(BaseModel):id:strvalue:strresponses={404:{"description":"Item not found"},302:{"description":"The item was moved"},403:{"description":"Not enough privileges"},}app=FastAPI()@app.get("/items/{item_id}",response_model=Item,responses={**responses,200:{"content":{"image/png":{}}}},)asyncdefread_item(item_id:str,img:Union[bool,None]=None):ifimg:returnFileResponse("image.png",media_type="image/png")else:return{"id":"foo","value":"there goes my hero"}
Objeto de Retorno OpenAPI, você pode incluir qualquer coisa dele diretamente em cada retorno dentro do seu parâmetro responses. Incluindo description, headers, content (dentro dele que você declara diferentes media types e esquemas JSON), e links.