Saltar al contenido

Usando Dataclasses

FastAPI está construido sobre Pydantic, y te he estado mostrando cómo usar modelos de Pydantic para declarar requests y responses.

Pero FastAPI también soporta usar dataclasses de la misma manera:

from dataclasses import dataclass

from fastapi import FastAPI


@dataclass
class Item:
    name: str
    price: float
    description: str | None = None
    tax: float | None = None


app = FastAPI()


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

Esto sigue siendo soportado gracias a Pydantic, ya que tiene soporte interno para dataclasses.

Así que, incluso con el código de arriba que no usa Pydantic explícitamente, FastAPI está usando Pydantic para convertir esos dataclasses estándar a la propia versión de dataclasses de Pydantic.

Y por supuesto, soporta lo mismo:

  • validación de datos
  • serialización de datos
  • documentación de datos, etc.

Esto funciona de la misma manera que con los modelos de Pydantic. Y de hecho se logra de la misma manera por debajo, usando Pydantic.

Nota

Ten en cuenta que los dataclasses no pueden hacer todo lo que los modelos de Pydantic pueden hacer.

Así que, es posible que aún necesites usar modelos de Pydantic.

Pero si tienes un montón de dataclasses por ahí, este es un buen truco para usarlos para potenciar una API web usando FastAPI. 🤓

Dataclasses en response_model

También puedes usar dataclasses en el parámetro response_model:

from dataclasses import dataclass, field

from fastapi import FastAPI


@dataclass
class Item:
    name: str
    price: float
    tags: list[str] = field(default_factory=list)
    description: str | None = None
    tax: float | None = None


app = FastAPI()


@app.get("/items/next", response_model=Item)
async def read_next_item():
    return {
        "name": "Island In The Moon",
        "price": 12.99,
        "description": "A place to be playin' and havin' fun",
        "tags": ["breater"],
    }

El dataclass será convertido automáticamente a un dataclass de Pydantic.

De esta manera, su schema aparecerá en la interfaz de usuario de la documentación de la API:

Dataclasses en Estructuras de Datos Anidadas

También puedes combinar dataclasses con otras anotaciones de tipo para hacer estructuras de datos anidadas.

En algunos casos, es posible que aún tengas que usar la versión de dataclasses de Pydantic. Por ejemplo, si tienes errores con la documentación de la API generada automáticamente.

En ese caso, puedes simplemente intercambiar los dataclasses estándar con pydantic.dataclasses, que es un reemplazo directo:

from dataclasses import field  # (1)

from fastapi import FastAPI
from pydantic.dataclasses import dataclass  # (2)


@dataclass
class Item:
    name: str
    description: str | None = None


@dataclass
class Author:
    name: str
    items: list[Item] = field(default_factory=list)  # (3)


app = FastAPI()


@app.post("/authors/{author_id}/items/", response_model=Author)  # (4)
async def create_author_items(author_id: str, items: list[Item]):  # (5)
    return {"name": author_id, "items": items}  # (6)


@app.get("/authors/", response_model=list[Author])  # (7)
def get_authors():  # (8)
    return [  # (9)
        {
            "name": "Breaters",
            "items": [
                {
                    "name": "Island In The Moon",
                    "description": "A place to be playin' and havin' fun",
                },
                {"name": "Holy Buddies"},
            ],
        },
        {
            "name": "System of an Up",
            "items": [
                {
                    "name": "Salt",
                    "description": "The kombucha mushroom people's favorite",
                },
                {"name": "Pad Thai"},
                {
                    "name": "Lonely Night",
                    "description": "The mostests lonliest nightiest of allest",
                },
            ],
        },
    ]
  1. Todavía importamos field de los dataclasses estándar.

  2. pydantic.dataclasses es un reemplazo directo para dataclasses.

  3. El dataclass Author incluye una lista de dataclasses Item.

  4. El dataclass Author se usa como el parámetro response_model.

  5. Puedes usar otras anotaciones de tipo estándar con dataclasses como cuerpo de la request.

    En este caso, es una lista de dataclasses Item.

  6. Aquí estamos retornando un diccionario que contiene items que es una lista de dataclasses.

    FastAPI sigue siendo capaz de serializar los datos a JSON.

  7. Aquí el response_model está usando una anotación de tipo de una lista de dataclasses Author.

    De nuevo, puedes combinar dataclasses con anotaciones de tipo estándar.

  8. Notá que esta función path operation usa def regular en lugar de async def.

    Como siempre, en FastAPI puedes combinar def y async def según sea necesario.

    Si necesitas un repaso sobre cuándo usar cuál, revisa la sección "¿Con prisa?" en la documentación sobre async y await.

  9. Esta función path operation no está retornando dataclasses (aunque podría), sino una lista de diccionarios con datos internos.

    FastAPI usará el parámetro response_model (que incluye dataclasses) para convertir la respuesta.

Puedes combinar dataclasses con otras anotaciones de tipo en muchas combinaciones diferentes para formar estructuras de datos complejas.

Revisa los tips de anotaciones en el código de arriba para ver más detalles específicos.

Aprende Más

También puedes combinar dataclasses con otros modelos de Pydantic, heredar de ellos, incluirlos en tus propios modelos, etc.

Para aprender más, revisa la documentación de Pydantic sobre dataclasses.

Versión

Esto está disponible desde la versión 0.67.0 de FastAPI. 🔖