Saltar al contenido

Códigos de Estado Adicionales

Por defecto, FastAPI devolverá las respuestas usando un JSONResponse, poniendo el contenido que devuelves desde tu path operation dentro de ese JSONResponse.

Usará el código de estado por defecto o el que establezcas en tu path operation.

Códigos de estado adicionales

Si quieres devolver códigos de estado adicionales aparte del principal, puedes hacerlo devolviendo una Response directamente, como un JSONResponse, y establecer el código de estado adicional directamente.

Por ejemplo, digamos que quieres tener una path operation que permita actualizar items, y devuelva códigos de estado HTTP de 200 "OK" cuando sea exitoso.

Pero también quieres que acepte items nuevos. Y cuando los items no existían antes, los crea, y devuelve un código de estado HTTP de 201 "Created".

Para lograr eso, importa JSONResponse, y devuelve tu contenido ahí directamente, estableciendo el status_code que quieras:

from typing import Annotated

from fastapi import Body, FastAPI, status
from fastapi.responses import JSONResponse

app = FastAPI()

items = {"foo": {"name": "Fighters", "size": 6}, "bar": {"name": "Tenders", "size": 3}}


@app.put("/items/{item_id}")
async def upsert_item(
    item_id: str,
    name: Annotated[str | None, Body()] = None,
    size: Annotated[int | None, Body()] = None,
):
    if item_id in items:
        item = items[item_id]
        item["name"] = name
        item["size"] = size
        return item
    else:
        item = {"name": name, "size": size}
        items[item_id] = item
        return JSONResponse(status_code=status.HTTP_201_CREATED, content=item)
🤓 Otras versiones y variantes

Consejo

Preferible usar la versión con Annotated si es posible.

from fastapi import Body, FastAPI, status
from fastapi.responses import JSONResponse

app = FastAPI()

items = {"foo": {"name": "Fighters", "size": 6}, "bar": {"name": "Tenders", "size": 3}}


@app.put("/items/{item_id}")
async def upsert_item(
    item_id: str,
    name: str | None = Body(default=None),
    size: int | None = Body(default=None),
):
    if item_id in items:
        item = items[item_id]
        item["name"] = name
        item["size"] = size
        return item
    else:
        item = {"name": name, "size": size}
        items[item_id] = item
        return JSONResponse(status_code=status.HTTP_201_CREATED, content=item)

Aviso

Cuando devuelves una Response directamente, como en el ejemplo anterior, se devolverá directamente.

No se serializará con un modelo, etc.

Asegúrate de que tenga los datos que quieres que tenga, y que los valores sean JSON válido (si estás usando JSONResponse).

Detalles Técnicos

También podrías usar from starlette.responses import JSONResponse.

FastAPI proporciona las mismas starlette.responses como fastapi.responses solo como una comodidad para ti, el desarrollador. Pero la mayoría de las respuestas disponibles vienen directamente de Starlette. Lo mismo con status.

OpenAPI y documentación de la API

Si devuelves códigos de estado y respuestas adicionales directamente, no se incluirán en el esquema de OpenAPI (la documentación de la API), porque FastAPI no tiene forma de saber de antemano lo que vas a devolver.

Pero puedes documentar eso en tu código, usando: Additional Responses.