Guía FastAPI: API de Ejemplo con Documentación Automática
¡Nota importante! Este tutorial incluye un API de prueba funcional y muestra cómo aprovechar el sistema de documentación automática de FastAPI desde cero.
1. Instalación y Configuración del Entorno
a) Verificar Python
Asegúrate de tener Python 3.7 o superior instalado:
python --version
b) Crear un directorio para el proyecto
mkdir fastapi-ejemplo
cd fastapi-ejemplo
c) Crear entorno virtual
Es fundamental usar un entorno virtual para evitar conflictos de dependencias:
# Windows
python -m venv venv
# macOS/Linux
python3 -m venv venv
d) Activar el entorno virtual
# Windows
venv\Scripts\activate
# macOS/Linux
source venv/bin/activate
¡Importante! Cuando el entorno virtual esté activo, verás
(venv)
al inicio de tu prompt. Siempre activa el entorno virtual antes de trabajar en el proyecto.
e) Instalar dependencias
pip install fastapi uvicorn[standard]
Donde:
- fastapi: El framework principal
- uvicorn: Servidor ASGI de alto rendimiento
- [standard]: Incluye dependencias adicionales recomendadas
f) Crear archivo requirements.txt
Para documentar las dependencias del proyecto:
pip freeze > requirements.txt
2. API de Ejemplo Completa
Crea un archivo main.py
con endpoints demostrativos:
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional
app = FastAPI(
title="API de Ejemplo",
description="API demostrativa con documentación automática",
version="1.0.0"
)
# Modelo Pydantic para validación
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
class ItemResponse(BaseModel):
id: int
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
# Base de datos ficticia
fake_db = {
1: {"name": "Laptop", "price": 999.99, "description": "Laptop gamer", "tax": 0.15},
2: {"name": "Mouse", "price": 25.50, "description": "Mouse inalámbrico", "tax": 0.10}
}
@app.get("/")
async def root():
"""Endpoint raíz que devuelve un mensaje de bienvenida"""
return {
"message": "Bienvenido a la API de ejemplo",
"version": "1.0.0",
"endpoints": {
"items": "/items",
"docs": "/docs o /redoc"
}
}
@app.get("/items/", response_model=dict)
async def read_items():
"""Devuelve todos los items de la base de datos ficticia"""
return fake_db
@app.get("/items/{item_id}", response_model=dict)
async def read_item(item_id: int):
"""
Devuelve un item específico por ID
- **item_id**: ID del item a buscar (debe existir)
"""
if item_id not in fake_db:
raise HTTPException(status_code=404, detail="Item no encontrado")
return {"id": item_id, **fake_db[item_id]}
@app.post("/items/", response_model=ItemResponse)
async def create_item(item: Item):
"""
Crea un nuevo item en la base de datos
- **name**: Nombre del item (requerido)
- **description**: Descripción opcional
- **price**: Precio (requerido)
- **tax**: Impuesto opcional
"""
new_id = max(fake_db.keys()) + 1 if fake_db else 1
fake_db[new_id] = item.dict()
return {"id": new_id, **fake_db[new_id]}
@app.put("/items/{item_id}", response_model=ItemResponse)
async def update_item(item_id: int, item: Item):
"""
Actualiza un item existente
- **item_id**: ID del item a actualizar
- **item**: Datos del item actualizados
"""
if item_id not in fake_db:
raise HTTPException(status_code=404, detail="Item no encontrado")
fake_db[item_id] = item.dict()
return {"id": item_id, **fake_db[item_id]}
@app.delete("/items/{item_id}")
async def delete_item(item_id: int):
"""
Elimina un item de la base de datos
- **item_id**: ID del item a eliminar
"""
if item_id not in fake_db:
raise HTTPException(status_code=404, detail="Item no encontrado")
deleted_item = fake_db.pop(item_id)
return {"message": "Item eliminado exitosamente", "deleted_item": deleted_item}
@app.get("/health")
async def health_check():
"""Endpoint de salud para verificar que la API está funcionando"""
return {"status": "healthy", "message": "API funcionando correctamente"}
3. Probando la API
Ejecuta el servidor de desarrollo:
uvicorn main:app --reload
Verás una salida similar a:
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) INFO: Started reloader process [12345] INFO: Started server process [12346] INFO: Waiting for application startup.
Endpoints disponibles:
- GET / - Página de inicio con información de la API
- GET /items/ - Lista todos los items
- GET /items/{id} - Obtiene un item específico
- POST /items/ - Crea un nuevo item
- PUT /items/{id} - Actualiza un item existente
- DELETE /items/{id} - Elimina un item
- GET /health - Verifica el estado de la API
Ejemplo de respuesta (GET /items/1):
{ "id": 1, "name": "Laptop", "price": 999.99, "description": "Laptop gamer", "tax": 0.15 }
4. Documentación Automática
FastAPI genera automáticamente dos tipos de documentación interactiva:
a) Swagger UI (interactiva)
Accede en http://127.0.0.1:8000/docs
- Permite probar los endpoints directamente desde el navegador
- Muestra esquemas de request/response
- Incluye los docstrings como descripciones
- Validación automática de parámetros
b) ReDoc (documentación estática)
Accede en http://127.0.0.1:8000/redoc
- Presentación más limpia para lectura
- Organiza los endpoints por categorías
- Mejor para documentación formal
¿Cómo funciona? FastAPI usa los estándares OpenAPI y JSON Schema.
Toda la documentación se genera automáticamente a partir de:
- Tipos de parámetros y modelos Pydantic
- Docstrings en las funciones
- Parámetros adicionales en la clase FastAPI
- Decoradores response_model
5. Personalizando la Documentación
Puedes mejorar la documentación con más detalles:
@app.get("/items/{item_id}",
summary="Obtener item por ID",
response_description="Los datos del item solicitado",
tags=["items"])
async def read_item(item_id: int):
"""
Devuelve un item específico por ID
Este endpoint permite obtener la información completa de un item
utilizando su identificador único.
- **item_id**: ID numérico del item (debe existir en la base de datos)
- **returns**: Diccionario con id, name, price, description y tax del item
## Ejemplo de uso:
```
GET /items/1
```
## Respuesta exitosa:
```json
{
"id": 1,
"name": "Laptop",
"price": 999.99,
"description": "Laptop gamer",
"tax": 0.15
}
```
"""
if item_id not in fake_db:
raise HTTPException(
status_code=404,
detail="Item no encontrado",
headers={"X-Error": "ID inválido"}
)
return {"id": item_id, **fake_db[item_id]}
Elementos adicionales para mejorar la documentación:
summary
: Breve descripción del endpointresponse_description
: Explicación de la respuestatags
: Agrupación de endpoints en la documentación- Docstring en Markdown: Se renderiza en la UI
- Ejemplos de código y respuestas
- Errores: Los
HTTPException
también se documentan
6. Probando con cURL
Ejemplos de cómo probar la API desde la línea de comandos:
# Obtener todos los items
curl http://127.0.0.1:8000/items/
# Obtener un item específico
curl http://127.0.0.1:8000/items/1
# Crear un nuevo item
curl -X POST "http://127.0.0.1:8000/items/" \
-H "Content-Type: application/json" \
-d '{
"name": "Teclado",
"description": "Teclado mecánico",
"price": 75.00,
"tax": 0.12
}'
# Verificar estado de la API
curl http://127.0.0.1:8000/health
7. Estructura del Proyecto
Tu proyecto debería tener la siguiente estructura:
fastapi-ejemplo/
├── venv/ # Entorno virtual
├── main.py # Archivo principal de la API
├── requirements.txt # Dependencias del proyecto
└── README.md # Documentación del proyecto (opcional)
8. Siguientes Pasos
Para continuar desarrollando tu API, puedes:
- Agregar autenticación y autorización
- Conectar una base de datos real (PostgreSQL, MySQL, etc.)
- Implementar middleware para logging y CORS
- Agregar tests unitarios
- Configurar variables de entorno
- Desplegar en producción
¡Consejo! La documentación automática es una de las principales ventajas de FastAPI.
Siempre escribe buenos docstrings y utiliza modelos Pydantic para obtener documentación de alta calidad automáticamente.
Comentarios
Publicar un comentario