Module 6: Project — CRUD API (To-Do List)

Proyecto Final: To-Do List API

Descripción

Has pasado cinco módulos aprendiendo FastAPI pieza por pieza. Instalaste el framework, creaste endpoints, manejaste parámetros, definiste modelos Pydantic, implementaste error handling profesional y configuraste CORS. Cada módulo agregó una capa sobre el anterior, y tu Books API evolucionó de un "Hello World" a una API robusta con validación, filtros, paginación y errores consistentes.

Ahora viene la prueba real: construir algo desde cero.

Este módulo es diferente a los anteriores. No hay conceptos nuevos. No hay teoría nueva. Todo lo que necesitas ya lo aprendiste. Lo que vas a hacer es tomar esos conocimientos fragmentados y combinarlos en un proyecto completo, profesional, que podrías mostrar en tu GitHub como demostración de tus habilidades con FastAPI.

El proyecto es un To-Do List API: una API REST completa para gestionar tareas con prioridades, estados, filtros, paginación, error handling y documentación. Es suficientemente simple para completarlo en una sesión intensiva, pero suficientemente complejo para demostrar que dominas todos los fundamentals de FastAPI.


¿Qué vas a construir?

Un API REST completo con estas características:

To-Do List API
├── CRUD completo de tareas
│   ├── POST   /tasks          → Crear tarea
│   ├── GET    /tasks          → Listar (con filtros y paginación)
│   ├── GET    /tasks/{id}     → Obtener una tarea
│   ├── PUT    /tasks/{id}     → Actualizar completo
│   ├── PATCH  /tasks/{id}     → Actualizar parcial
│   └── DELETE /tasks/{id}     → Eliminar
│
├── Endpoints adicionales
│   ├── GET    /tasks/stats    → Estadísticas de tareas
│   └── GET    /health         → Health check
│
├── Filtros por query params
│   ├── status (pending, in_progress, completed)
│   ├── priority (low, medium, high)
│   ├── search (texto en título y descripción)
│   ├── skip / limit (paginación)
│
├── Modelos Pydantic separados
│   ├── TaskCreate   → Para crear tareas
│   ├── TaskUpdate   → Para PUT (reemplazo completo)
│   ├── TaskPatch    → Para PATCH (actualización parcial)
│   └── TaskResponse → Para respuestas
│
├── Error handling profesional
│   ├── HTTPException con status codes correctos
│   └── Respuestas de error consistentes
│
├── CORS configurado
│   └── Acceso desde frontends de desarrollo
│
└── Documentación /docs personalizada
    └── Título, descripción, versión, tags

Lo que NO incluye este proyecto

  • ❌ Base de datos — los datos se almacenan en memoria (lista de dicts)
  • ❌ Autenticación — no hay login, tokens ni permisos
  • ❌ Deployment — todo corre en localhost
  • ❌ Tests automatizados — verificas manualmente con /docs y curl

Estos límites son intencionales. El objetivo es demostrar que dominas FastAPI, no construir una aplicación de producción completa. Las bases de datos, autenticación y deployment vienen en las guías siguientes del path.

Ejemplo de interacción con la API terminada

Así se ve la API en acción cuando esté completa:

# Crear una tarea
curl -X POST http://127.0.0.1:8000/tasks \
  -H "Content-Type: application/json" \
  -d '{"title": "Estudiar FastAPI avanzado", "priority": "high"}'
# → 201 Created con id, created_at, updated_at

# Listar tareas pendientes de alta prioridad
curl "http://127.0.0.1:8000/tasks?status=pending&priority=high"
# → 200 OK con lista filtrada y metadata de paginación

# Marcar como completada
curl -X PATCH http://127.0.0.1:8000/tasks/1 \
  -H "Content-Type: application/json" \
  -d '{"status": "completed"}'
# → 200 OK, solo status y updated_at cambiaron

# Pedir tarea inexistente
curl http://127.0.0.1:8000/tasks/999
# → 404 {"status": "error", "code": "HTTP_404", "message": "Task with id 999 not found"}

Esa es la experiencia que ofrece tu API: respuestas claras, errores informativos, filtros útiles. Todo construido con los conceptos que ya dominas.


Arquitectura del proyecto

A diferencia de los módulos anteriores donde todo vivía en app/main.py, este proyecto tiene una estructura de carpetas profesional:

todo-api/
├── app/
│   ├── __init__.py        # Marca app/ como paquete Python
│   ├── main.py            # Configuración de la app, middleware, docs
│   ├── models.py          # Modelos Pydantic (TaskCreate, TaskResponse, etc.)
│   ├── routes.py          # Todos los endpoints
│   └── data.py            # Almacenamiento en memoria + helpers
├── requirements.txt       # Dependencias del proyecto
└── README.md              # Documentación del proyecto

¿Por qué esta estructura?

ArchivoResponsabilidadAnalogía
main.pyConfiguración global: FastAPI app, CORS, docs metadata, exception handlersEl "cerebro" de la app — configura todo pero no tiene endpoints
models.pyDefinición de datos: qué acepta y qué retorna la APILos "contratos" — define la forma de los datos
routes.pyLógica de negocio: los endpoints que procesan requestsLas "manos" — ejecutan las operaciones
data.pyAlmacenamiento: dónde viven los datos y cómo se buscanLa "memoria" — guarda y busca datos

La ventaja: cuando necesites modificar un modelo, vas a models.py. Cuando necesites agregar un endpoint, vas a routes.py. Cuando necesites cambiar cómo se almacenan los datos (por ejemplo, migrar a base de datos), solo cambias data.py. Cada archivo tiene una responsabilidad clara.


¿Dónde estamos en la guía?

Estás en el Módulo 6 de 6 de la guía FastAPI Fundamentals:

Módulo 1: Setup y Primera API ✅
    → Instalación, uvicorn, endpoints GET, documentación automática

Módulo 2: Path Operations ✅
    → GET, POST, PUT, PATCH, DELETE — CRUD completo

Módulo 3: Request y Response ✅
    → Query params, Path(), Query(), Body(), filtros, paginación

Módulo 4: Pydantic y Validación ✅
    → BaseModel, Field(), validators, modelos separados, response_model

Módulo 5: Error Handling y CORS ✅
    → HTTPException, custom handlers, CORS middleware, status codes

Módulo 6: Proyecto Final — To-Do List API ← ESTÁS AQUÍ
    → Integración total: construye un CRUD API desde cero

Integración de conceptos

Cada módulo te dio una herramienta. Ahora las usas todas juntas:

MóduloConceptoCómo se usa en el proyecto
1Setup, uvicorn, /docsEstructura profesional, documentación personalizada
2GET, POST, PUT, PATCH, DELETECRUD completo de tareas
3Query params, path params, paginaciónFiltros por status, priority, search + skip/limit
4Pydantic models, Field, validatorsTaskCreate, TaskUpdate, TaskPatch, TaskResponse
5HTTPException, CORS, status codesError handling consistente, CORS para frontends

Especificaciones técnicas

Entidad: Task

Cada tarea tiene estos campos:

CampoTipoRequeridoDescripción
idintAuto-generadoIdentificador único
titlestrTítulo de la tarea (1-100 caracteres)
descriptionstrNoDescripción detallada (default: "")
statusStatusNoEstado: pending, in_progress, completed (default: pending)
priorityPriorityNoPrioridad: low, medium, high (default: medium)
created_atdatetimeAuto-generadoFecha/hora de creación
updated_atdatetimeAuto-generadoFecha/hora de última actualización

Enums

class Status(str, Enum):
    pending = "pending"
    in_progress = "in_progress"
    completed = "completed"

class Priority(str, Enum):
    low = "low"
    medium = "medium"
    high = "high"

Endpoints

MétodoRutaStatus OKDescripción
GET/health200Health check
POST/tasks201Crear tarea
GET/tasks200Listar tareas (con filtros)
GET/tasks/stats200Estadísticas
GET/tasks/{task_id}200Obtener tarea por ID
PUT/tasks/{task_id}200Actualización completa
PATCH/tasks/{task_id}200Actualización parcial
DELETE/tasks/{task_id}204Eliminar tarea

Filtros (GET /tasks)

ParámetroTipoDescripción
statusStatus (optional)Filtrar por estado
priorityPriority (optional)Filtrar por prioridad
searchstr (optional)Buscar en título y descripción
skipint (default: 0)Saltar N resultados
limitint (default: 10, max: 100)Máximo de resultados

Rúbrica de evaluación (100 puntos)

Esta es tu rúbrica para autoevaluarte al terminar. Cada sección tiene puntos asignados.

Estructura del proyecto (10 puntos)

  • (2 pts) Carpeta todo-api/ con estructura app/ correcta
  • (2 pts) __init__.py presente en app/
  • (2 pts) Separación en main.py, models.py, routes.py, data.py
  • (2 pts) requirements.txt con dependencias
  • (2 pts) README.md con instrucciones de setup y endpoints

Modelos Pydantic (20 puntos)

  • (4 pts) Status y Priority como str, Enum
  • (4 pts) TaskCreate con validación de title (min 1, max 100 chars)
  • (4 pts) TaskUpdate para reemplazo completo
  • (4 pts) TaskPatch con todos los campos opcionales
  • (4 pts) TaskResponse con id, created_at, updated_at

Endpoints CRUD (30 puntos)

  • (5 pts) POST /tasks → crea tarea con id auto-generado y timestamps
  • (5 pts) GET /tasks → lista con filtros por status, priority, search
  • (5 pts) GET /tasks → paginación con skip/limit
  • (5 pts) GET /tasks/{task_id} → retorna tarea o 404
  • (5 pts) PUT /tasks/{task_id} → actualización completa o 404
  • (3 pts) PATCH /tasks/{task_id} → actualización parcial, 400 si body vacío
  • (2 pts) DELETE /tasks/{task_id} → elimina o 404

Error handling (15 puntos)

  • (5 pts) HTTPException con status codes correctos: 400, 404, 422
  • (5 pts) Formato de error consistente en toda la API
  • (5 pts) Todos los edge cases cubiertos (ID no existe, body vacío, etc.)

Extras (15 puntos)

  • (5 pts) GET /tasks/stats con conteos por status y priority
  • (3 pts) GET /health endpoint
  • (4 pts) CORS configurado con CORSMiddleware
  • (3 pts) /docs personalizado con título, descripción, versión

Calidad de código (10 puntos)

  • (3 pts) Enums para status y priority (no strings mágicos)
  • (3 pts) model_dump() en vez de .dict() (Pydantic v2)
  • (2 pts) Type hints en todas las funciones
  • (2 pts) Código limpio, sin duplicación innecesaria

Roadmap del proyecto

El proyecto se construye en 4 cápsulas incrementales. Cada una agrega una capa:

CápsulaQué construyesResultado
02Setup + Modelos + DatosEstructura de proyecto, modelos Pydantic, datos iniciales
03Endpoints CRUDTodos los endpoints funcionando con filtros y paginación
04Error handling + CORS + DocsErrores profesionales, CORS, stats, health, docs custom
05Verificación + EntregaTesting completo, rúbrica, código final, README, retrospectiva

Flujo de construcción

Cápsula 02: Cimientos
├── Crear todo-api/ con estructura de carpetas
├── Definir modelos Pydantic en models.py
├── Configurar datos iniciales en data.py
└── App básica en main.py
    ↓
Cápsula 03: Funcionalidad
├── Implementar POST /tasks
├── Implementar GET /tasks con filtros
├── Implementar GET /tasks/{task_id}
├── Implementar PUT /tasks/{task_id}
├── Implementar PATCH /tasks/{task_id}
└── Implementar DELETE /tasks/{task_id}
    ↓
Cápsula 04: Profesionalismo
├── Error handling consistente
├── CORS middleware
├── GET /health
├── GET /tasks/stats
└── /docs personalizado
    ↓
Cápsula 05: Entrega
├── Testing manual completo
├── Autoevaluación con rúbrica
├── Código final verificado
├── README.md del proyecto
└── Retrospectiva

Cada cápsula termina con una versión funcional. Después de la cápsula 02 tienes la estructura lista. Después de la 03, el CRUD funciona. Después de la 04, la API es profesional. Después de la 05, está lista para entregar.


Antes de empezar

Verificación de prerequisitos

Asegúrate de tener todo listo antes de comenzar:

python --version
# Python 3.9+ requerido

pip install fastapi uvicorn
# O verifica que ya están instalados:
pip show fastapi uvicorn

Lo que ya sabes (y vas a usar)

De los módulos anteriores traes estas habilidades:

  • ✅ Crear un proyecto FastAPI con virtual environment
  • ✅ Correr el servidor con uvicorn app.main:app --reload
  • ✅ Definir endpoints con todos los verbos HTTP
  • ✅ Usar path params, query params y request body
  • ✅ Crear modelos Pydantic con BaseModel, Field(), @field_validator
  • ✅ Usar model_dump(), model_dump(exclude_unset=True) para PATCH
  • ✅ Configurar response_model en endpoints
  • ✅ Lanzar HTTPException con status codes semánticos
  • ✅ Agregar CORSMiddleware para acceso cross-origin
  • ✅ Personalizar metadata de /docs

Si algo de esta lista no te resulta familiar, repasa la cápsula correspondiente antes de continuar. Este proyecto asume que dominas todos estos conceptos.


Mentalidad para el proyecto

Este módulo no te va paso a paso como los anteriores. No te dice "escribe esta línea, ahora esta otra." Te da especificaciones, código completo de referencia, y explicaciones de diseño. Tú escribes el código en tu editor, lo pruebas, y lo ajustas.

¿Por qué? Porque así funciona el desarrollo real. En un trabajo, no te dan un tutorial paso a paso. Te dan requisitos y tú implementas. Este proyecto simula esa experiencia.

Consejo: Lee toda la cápsula antes de escribir código. Entiende qué vas a construir, y después impleméntalo. Si te atoras, el código de referencia está ahí — pero intenta primero.

Cómo usar el código de referencia

Cada cápsula incluye el código completo. La forma recomendada de usarlo:

  1. Lee la especificación completa — entiende qué debe hacer el archivo
  2. Intenta escribirlo tú — abre tu editor y escribe el código desde cero
  3. Compara con la referencia — verifica que tu implementación cubre todos los casos
  4. Ajusta si es necesario — corrige diferencias que afecten la funcionalidad
  5. Prueba — ejecuta el servidor y verifica con /docs o curl

No hay una sola forma "correcta" de implementar cada endpoint. Si tu código funciona y cubre los requisitos, es válido aunque sea diferente al código de referencia.


El To-Do List API como portfolio piece

Este proyecto está diseñado para ir en tu GitHub como evidencia de tus habilidades FastAPI. Un buen proyecto de portafolio tiene:

  • README claro — cualquier persona puede clonar, instalar y correr tu API en minutos
  • Estructura profesional — carpetas organizadas, no todo en un archivo
  • Código limpio — type hints, nombres descriptivos, sin comentarios obvios
  • Features completas — no un CRUD básico, sino filtros, paginación, error handling
  • Documentación automática/docs funcionando y personalizado

La Books API que construiste en los módulos 1-5 fue un ejercicio de aprendizaje incremental. El To-Do List API es tu primer proyecto "from scratch" — demuestra que puedes tomar requisitos y convertirlos en un API funcional sin guía paso a paso.

¿Qué dice tu API sobre ti?

Cuando un reclutador o un tech lead revisa tu proyecto en GitHub, busca señales de profesionalismo:

SeñalTu API la tiene
Estructura organizadaapp/ con archivos separados por responsabilidad
Validación de datosPydantic models con constraints y validators
Error handlingStatus codes correctos, formato de error consistente
DocumentaciónREADME con setup + /docs automático personalizado
Buenas prácticasEnums, type hints, CORS, logging

No necesitas un proyecto gigante. Necesitas un proyecto bien hecho. Este lo es.


Resumen

  • Este es el Módulo 6: el proyecto final integrador de toda la guía FastAPI Fundamentals
  • Construirás un To-Do List API completo desde cero con estructura profesional
  • El proyecto integra todos los conceptos de los módulos 1-5: setup, CRUD, params, Pydantic, error handling, CORS
  • La arquitectura separa responsabilidades: main.py (config), models.py (datos), routes.py (endpoints), data.py (almacenamiento)
  • 100 puntos distribuidos en estructura, modelos, CRUD, error handling, extras y calidad
  • Datos en memoria (sin base de datos), sin autenticación, sin deployment
  • 4 cápsulas de construcción: setup → CRUD → profesionalismo → entrega
  • No hay conceptos nuevos — este proyecto demuestra que dominas lo que aprendiste

Recursos adicionales

  1. FastAPI - Tutorial completo — Referencia oficial de todos los conceptos que usarás
  2. FastAPI - Project Structure — Cómo organizar aplicaciones más grandes
  3. Pydantic v2 - Models — Referencia de BaseModel y Field
  4. Python - Enum — Documentación oficial de enumeraciones
  5. HTTP Status Codes - MDN — Referencia de status codes
  6. FastAPI - CORS — Configuración de CORSMiddleware

Siguiente cápsula: Setup, modelos y datos — Crearás la estructura del proyecto, definirás todos los modelos Pydantic con Enums y timestamps, configurarás los datos iniciales, y tendrás la app lista para recibir endpoints.