FastAPI ha emergido como uno de los frameworks más revolucionarios para desarrollar APIs en Python. Combinando un rendimiento excepcional con una sintaxis elegante e intuitiva, te permite crear APIs robustas en tiempo récord. Si buscas crear una API RESTful con Python que sea rápida, segura y fácil de mantener, FastAPI es la elección ideal.
🚀 ¿Qué Hace Especial a FastAPI?
FastAPI no es solo otro framework web. Es una herramienta construida sobre estándares modernos que establece un nuevo paradigma en el ecosistema de Python. A diferencia de los frameworks tradicionales, FastAPI ofrece validación automática de datos mediante Pydantic, documentación automática e interactiva con Swagger UI, y rendimiento comparable a Node.js y Go.
La documentación automática generada por FastAPI es particularmente impresionante. Al acceder al endpoint `/docs` en producción, obtienes una interfaz interactiva para probar todos los endpoints de tu API sin escribir una línea de código adicional. Esto representa un ahorro significativo de tiempo en el desarrollo y en la colaboración entre equipos.
Para comprender el poder de FastAPI, imagina crear una API que valida automáticamente los datos de entrada, genera documentación en tiempo real, y se ejecuta a velocidades comparables a lenguajes compilados. Todo esto con Python, un lenguaje conocido por su productividad y legibilidad.
📦 Instalación y Configuración del Entorno
Antes de crear tu primera API, es fundamental configurar un entorno aislado. Recomendamos utilizar entornos virtuales para evitar conflictos entre dependencias de diferentes proyectos.
# Crear entorno virtual
python -m venv venv
# Activar entorno virtual (Linux/Mac)
source venv/bin/activate
# Activar entorno virtual (Windows)
venv\Scripts\activate
# Instalar FastAPI y servidor Uvicorn
pip install fastapi uvicorn[standard]
# Instalar herramientas adicionales
pip install pydantic python-multipart python-jose[cryptography] passlib[bcrypt]
Uvicorn es el servidor ASGI (Asynchronous Server Gateway Interface) que permite ejecutar aplicaciones FastAPI en alto rendimiento. La opción `[standard]` instala dependencias opcionales que mejoran aún más el rendimiento en producción. Python.org mantiene documentación oficial sobre la configuración de entornos virtuales.
🏗️ Creando Tu Primera API con FastAPI
Vamos a construir una API completa de tareas (to-do list) con funcionalidades reales. Comenzaremos simple y progresivamente añadiremos complejidad, ilustrando cómo FastAPI escala naturalmente hacia aplicaciones empresariales.
# main.py
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI(title="API de Tareas", version="1.0.0")
class Tarea(BaseModel):
id: int | None = None
titulo: str
descripcion: str | None = None
completada: bool = False
tareas = []
@app.get("/")
def raiz():
return {"mensaje": "API de Tareas en Línea", "status": "operacional"}
@app.get("/tareas")
def listar_tareas():
return tareas
@app.post("/tareas")
def crear_tarea(tarea: Tarea):
tarea.id = len(tareas) + 1
tareas.append(tarea)
return tarea
@app.get("/tareas/{tarea_id}")
def obtener_tarea(tarea_id: int):
for tarea in tareas:
if tarea.id == tarea_id:
return tarea
return {"error": "Tarea no encontrada"}
@app.put("/tareas/{tarea_id}")
def actualizar_tarea(tarea_id: int, tarea_actualizada: Tarea):
for tarea in tareas:
if tarea.id == tarea_id:
tarea.titulo = tarea_actualizada.titulo
tarea.descripcion = tarea_actualizada.descripcion
tarea.completada = tarea_actualizada.completada
return tarea
return {"error": "Tarea no encontrada"}
@app.delete("/tareas/{tarea_id}")
def eliminar_tarea(tarea_id: int):
for i, tarea in enumerate(tareas):
if tarea.id == tarea_id:
tareas.pop(i)
return {"mensaje": "Tarea eliminada"}
return {"error": "Tarea no encontrada"}
Para ejecutar la API, utiliza el comando:
uvicorn main:app --reload
El parámetro `--reload` hace que el servidor se reinicie automáticamente al detectar cambios en el código, fundamental durante el desarrollo. Accede a http://127.0.0.1:8000/docs para ver la documentación automática. El sitio oficial de FastAPI ofrece tutoriales detallados sobre esta estructura básica.
🔍 Validación Avanzada con Pydantic
La verdadera potencia de FastAPI emerge cuando se combina con Pydantic para una validación robusta. Déjame mostrarte cómo crear validaciones sofisticadas que anteriormente requerirían bibliotecas externas o código manualmente elaborado.
from pydantic import BaseModel, Field, validator
from typing import Optional
from datetime import datetime
class Usuario(BaseModel):
username: str = Field(min_length=3, max_length=50)
email: str
password: str = Field(min_length=8)
edad: Optional[int] = Field(None, ge=0, le=150)
fecha_registro: datetime = Field(default_factory=datetime.now)
@validator('email')
def validar_email(cls, v):
if '@' not in v or '.' not in v.split('@')[-1]:
raise ValueError('Email inválido')
return v.lower()
@validator('password')
def validar_password(cls, v):
if not any(c.isupper() for c in v):
raise ValueError('La contraseña debe contener mayúscula')
if not any(c.isdigit() for c in v):
raise ValueError('La contraseña debe contener número')
return v
class Producto(BaseModel):
nombre: str = Field(min_length=2, max_length=100)
precio: float = Field(gt=0, description="El precio debe ser positivo")
categoria: str
stock: int = Field(ge=0, description="Cantidad en inventario")
descripcion: Optional[str] = Field(None, max_length=500)
Pydantic ofrece validación automática con mensajes de error claros y descriptivos. La documentación de Pydantic detalla todos los tipos disponibles para validación, incluyendo validadores personalizados, campos anidados y modelos complejos. Este enfoque elimina una categoría completa de errores relacionados con datos inválidos.
🔐 Sistema de Autenticación JWT
La seguridad es fundamental en cualquier API profesional. Implementaremos autenticación usando JSON Web Tokens (JWT), el estándar moderno para APIs RESTful. JWT permite autenticación sin estado, ideal para arquitecturas distribuidas y microservicios.
from datetime import datetime, timedelta
from jose import JWTError, jwt
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
SECRET_KEY = "tu_clave_secreta_cambia_en_producción"
ALGORITHM = "HS256"
EXPIRACION_MINUTOS = 30
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
def crear_token_jwt(data: dict):
to_encode = data.copy()
expire = datetime.utcnow() + timedelta(minutes=EXPIRACION_MINUTOS)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
async def obtener_usuario_actual(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Credenciales inválidas",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise credentials_exception
return username
except JWTError:
raise credentials_exception
@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
# Aquí verificarías en la base de datos
if form_data.username == "admin" and form_data.password == "admin123":
access_token = crear_token_jwt(data={"sub": form_data.username})
return {"access_token": access_token, "token_type": "bearer"}
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Usuario o contraseña incorrectos"
)
@app.get("/protegido")
async def endpoint_protegido(usuario: str = Depends(obtener_usuario_actual)):
return {"mensaje": f"¡Bienvenido, {usuario}!"}
La implementación de JWT requiere atención especial a la seguridad. En producción, nunca codifiques la SECRET_KEY; utiliza variables de entorno. PyJWT ofrece documentación completa sobre generación y validación de tokens. OAuth 2.0 es el estándar de la industria para autorización en APIs modernas.
🗄️ Integración con Base de Datos SQLite
Para aplicaciones reales, necesitamos persistir datos. Utilizaremos SQLite por su simplicidad, pero la estructura sirve como base para PostgreSQL o MySQL. SQLAlchemy es el estándar para interacción con bases de datos en Python.
from sqlalchemy import create_engine, Column, Integer, String, Boolean
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from pydantic import BaseModel
SQLALCHEMY_DATABASE_URL = "sqlite:///./tareas.db"
engine = create_engine(
SQLALCHEMY_DATABASE_URL,
connect_args={"check_same_thread": False}
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
class TareaDB(Base):
__tablename__ = "tareas"
id = Column(Integer, primary_key=True, index=True)
titulo = Column(String, index=True)
descripcion = Column(String)
completada = Column(Boolean, default=False)
Base.metadata.create_all(bind=engine)
# Esquemas Pydantic
class TareaSchema(BaseModel):
titulo: str
descripcion: str | None = None
completada: bool = False
class Config:
from_attributes = True
# Funciones de base de datos
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.post("/tareas/", response_model=TareaSchema)
def crear_tarea(tarea: TareaSchema, db: Session = Depends(get_db)):
db_tarea = TareaDB(**tarea.model_dump())
db.add(db_tarea)
db.commit()
db.refresh(db_tarea)
return db_tarea
SQLite es perfecto para desarrollo y aplicaciones de pequeño porte. Para escala empresarial, PostgreSQL ofrece funciones avanzadas. La documentación de SQLAlchemy explica cómo migrar entre diferentes bases de datos manteniendo el mismo código.
🧪 Tests Automatizados con FastAPI
La calidad de código profesional requiere tests automatizados. FastAPI se integra perfectamente con pytest, permitiendo probar endpoints de forma simple y efectiva.
# test_main.py
from fastapi.testclient import TestClient
from main import app
client = TestClient(app)
def test_raiz():
response = client.get("/")
assert response.status_code == 200
assert "mensaje" in response.json()
def test_crear_tarea():
response = client.post("/tareas", json={
"titulo": "Nueva tarea",
"descripcion": "Descripción de la tarea",
"completada": False
})
assert response.status_code == 200
data = response.json()
assert data["titulo"] == "Nueva tarea"
assert "id" in data
def test_listar_tareas():
response = client.get("/tareas")
assert response.status_code == 200
assert isinstance(response.json(), list)
Ejecuta los tests con:
pytest test_main.py -v
El framework de tests de FastAPI permite probar escenarios complejos, incluyendo autenticación, subida de archivos y errores esperados. La documentación de pytest ofrece funciones avanzadas como fixtures, parametrización e integración continua.
🚀 Deploy en Producción
Cuando tu API esté lista para producción, existen varias opciones de hosting. Veremos las más populares y sus características.
Deploy en Render
Render ofrece gratuito para proyectos Python con tiempo limitado, ideal para comenzar. Configura el archivo `requirements.txt`:
fastapi
uvicorn[standard]
sqlalchemy
pydantic
python-jose[cryptography]
passlib[bcrypt]
python-multipart
Crea un archivo `render.yaml` o configura desde el panel web con comando de inicio: `uvicorn main:app --host 0.0.0.0 --port $PORT`.
Deploy en Railway
Railway ofrece deploy simple con soporte de base de datos integrado. Ideal para prototipos y MVPs.
Deploy en Heroku
Heroku fue pionero en Platform as a Service. Aunque ha reducido su nivel gratuito, sigue siendo opción válida para producción.
Docker y Contenedores
Para máxima portabilidad y control, crea un Dockerfile:
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Docker permite contenerizar tu aplicación, facilitando el deploy en cualquier plataforma que soporte contenedores, incluyendo Kubernetes, AWS ECS y Google Cloud Run.
📈 Mejores Prácticas y Patrones Arquitectónicos
A medida que tu aplicación crece, los patrones arquitectónicos se vuelven esenciales. Aquí tienes prácticas recomendadas para proyectos FastAPI profesionales.
Estructura de Proyectos
Organiza tu proyecto en módulos bien definidos:
proyecto/
├── app/
│ ├── __init__.py
│ ├── main.py
│ ├── routers/
│ │ ├── __init__.py
│ │ ├── tareas.py
│ │ └── usuarios.py
│ ├── models/
│ │ ├── __init__.py
│ │ └── database.py
│ ├── schemas/
│ │ ├── __init__.py
│ │ └── pydantic_models.py
│ └── services/
│ ├── __init__.py
│ └── business_logic.py
├── tests/
├── requirements.txt
└── README.md
Esta estructura de separación de responsabilidades facilita el mantenimiento y la testabilidad. Cada capa tiene responsabilidad clara: los routers manejan HTTP, los servicios contienen lógica de negocio, y los modelos definen la estructura de datos.
Rate Limiting
Protege tu API contra abuso implementando rate limiting:
from fastapi import FastAPI
from slowapi import Limiter
from slowapi.util import get_remote_address
limiter = Limiter(key_func=get_remote_address)
app = FastAPI()
@app.get("/endpoint-protegido")
@limiter.limit("10/minute")
async def endpoint_limitado():
return {"mensaje": "Respuesta limitada"}
Logging y Monitoreo
En producción, el monitoreo es esencial:
import logging
from fastapi import FastAPI
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
app = FastAPI()
@app.middleware("http")
async def log_requests(request, call_next):
logger.info(f"{request.method} {request.url}")
response = await call_next(request)
logger.info(f"Status: {response.status_code}")
return response
El módulo logging de Python ofrece configuración flexible para diferentes entornos. Para entornos empresariales, considera integrar con Datadog o New Relic.
🔗 Conclusión y Próximos Pasos
FastAPI representa una evolución significativa en el desarrollo de APIs con Python. Con su combinación de velocidad, productividad y características modernas, permite a los desarrolladores crear APIs profesionales en una fracción del tiempo necesario con frameworks tradicionales.
Los conceptos presentados en esta guía—from basic routing hasta autenticación JWT y deploy—forman la base para construir aplicaciones robustas y escalables. Continúa explorando la documentación oficial de FastAPI para profundizar tu conocimiento en middlewares, WebSockets y tests avanzados.
Para acelerar aún más tu aprendizaje, explora nuestros otros tutoriales sobre funciones Python, web scraping y análisis de datos con Pandas.
Ahora te toca a ti: comienza tu proyecto de API hoy mismo y experimenta la diferencia que FastAPI puede hacer en tu productividad como desarrollador.