Concepto y sintaxis básica con Depends()
La inyección de dependencias es un patrón de diseño que permite que nuestras funciones reciban automáticamente los recursos o servicios que necesitan, sin tener que crearlos directamente dentro de cada función. En FastAPI, este mecanismo se implementa mediante la función Depends()
, que actúa como un intermediario inteligente entre nuestras rutas y los recursos que requieren.
Imagina que tienes varias rutas en tu API que necesitan realizar la misma validación o preparar los mismos datos. Sin inyección de dependencias, tendrías que duplicar código en cada función. Con Depends()
, defines esa lógica una sola vez y FastAPI se encarga de ejecutarla automáticamente cuando sea necesaria.
Sintaxis fundamental
La sintaxis básica de Depends()
es sorprendentemente simple. Primero defines una función de dependencia que contiene la lógica que quieres reutilizar, y luego la inyectas en tus rutas usando Depends()
:
from fastapi import FastAPI, Depends
app = FastAPI()
def obtener_configuracion():
return {"version": "1.0", "debug": True}
@app.get("/info")
def mostrar_info(config: dict = Depends(obtener_configuracion)):
return {"mensaje": "API funcionando", "config": config}
En este ejemplo, obtener_configuracion()
es nuestra función de dependencia. FastAPI la ejecuta automáticamente antes de llamar a mostrar_info()
, y el resultado se pasa como parámetro config
.
Cómo funciona internamente
Cuando FastAPI encuentra Depends()
en los parámetros de una ruta, sigue este proceso automático:
- 1. Identifica la dependencia: Reconoce que
obtener_configuracion
debe ejecutarse primero - 2. Ejecuta la función: Llama a
obtener_configuracion()
y obtiene su resultado - 3. Inyecta el resultado: Pasa el valor devuelto como argumento a la función de la ruta
def validar_usuario_activo():
# Simulamos una validación
usuario_activo = True
if not usuario_activo:
raise HTTPException(status_code=403, detail="Usuario inactivo")
return {"usuario_id": 123, "activo": True}
@app.get("/perfil")
def obtener_perfil(usuario: dict = Depends(validar_usuario_activo)):
return {"perfil": f"Datos del usuario {usuario['usuario_id']}"}
@app.get("/configuracion")
def obtener_configuracion_usuario(usuario: dict = Depends(validar_usuario_activo)):
return {"configuracion": "Configuración personalizada", "usuario": usuario}
Observa cómo la misma función de dependencia se reutiliza en múltiples rutas. FastAPI ejecutará validar_usuario_activo()
automáticamente para cada ruta que la declare como dependencia.
Dependencias con parámetros
Las funciones de dependencia también pueden recibir parámetros de la petición HTTP, como query parameters o path parameters:
def obtener_limite_paginacion(limite: int = 10, pagina: int = 1):
if limite > 100:
limite = 100
offset = (pagina - 1) * limite
return {"limite": limite, "offset": offset}
@app.get("/productos")
def listar_productos(paginacion: dict = Depends(obtener_limite_paginacion)):
# Simulamos obtener productos con paginación
productos = [f"Producto {i}" for i in range(paginacion["offset"],
paginacion["offset"] + paginacion["limite"])]
return {"productos": productos, "paginacion": paginacion}
En este caso, FastAPI extrae automáticamente los parámetros limite
y pagina
de la URL (como ?limite=20&pagina=2
) y los pasa a la función de dependencia.
Múltiples dependencias
Una ruta puede tener varias dependencias simultáneamente, y FastAPI las resolverá todas antes de ejecutar la función principal:
def obtener_timestamp():
from datetime import datetime
return datetime.now().isoformat()
def obtener_version_api():
return "v2.1.0"
@app.get("/estado")
def estado_sistema(
timestamp: str = Depends(obtener_timestamp),
version: str = Depends(obtener_version_api),
config: dict = Depends(obtener_configuracion)
):
return {
"estado": "operativo",
"timestamp": timestamp,
"version": version,
"configuracion": config
}
FastAPI ejecutará las tres funciones de dependencia en paralelo cuando sea posible, optimizando el rendimiento de tu API.
Ventajas inmediatas
El uso de Depends()
aporta beneficios tangibles desde el primer momento:
- Reutilización: Escribes la lógica una vez y la usas en múltiples rutas
- Mantenibilidad: Los cambios en una dependencia se aplican automáticamente a todas las rutas que la usan
- Testabilidad: Puedes probar las dependencias por separado y mockearlas fácilmente
- Legibilidad: El código de las rutas se centra en su lógica específica, no en preparar datos
La inyección de dependencias con Depends()
transforma tu código de FastAPI en algo más modular y profesional, eliminando la duplicación y facilitando el mantenimiento a largo plazo.
¿Te está gustando esta lección?
Inicia sesión para no perder tu progreso y accede a miles de tutoriales, ejercicios prácticos y nuestro asistente de IA.
Más de 25.000 desarrolladores ya confían en CertiDevs
Dependencias simples reutilizables
Una vez que dominas la sintaxis básica de Depends()
, el siguiente paso es crear dependencias reutilizables que resuelvan problemas comunes en tu API. Estas dependencias actúan como bloques de construcción que puedes combinar para crear funcionalidades más complejas sin duplicar código.
Dependencias para validación de datos
Las validaciones personalizadas son uno de los casos de uso más frecuentes para las dependencias reutilizables. En lugar de repetir la misma lógica de validación en múltiples rutas, puedes encapsularla en una dependencia:
from fastapi import FastAPI, Depends, HTTPException
app = FastAPI()
def validar_id_positivo(id: int):
if id <= 0:
raise HTTPException(status_code=400, detail="El ID debe ser un número positivo")
return id
@app.get("/usuarios/{user_id}")
def obtener_usuario(user_id: int = Depends(validar_id_positivo)):
return {"usuario_id": user_id, "nombre": f"Usuario {user_id}"}
@app.get("/productos/{product_id}")
def obtener_producto(product_id: int = Depends(validar_id_positivo)):
return {"producto_id": product_id, "nombre": f"Producto {product_id}"}
Esta dependencia garantiza consistencia en la validación de IDs a lo largo de toda tu API. Si necesitas cambiar la lógica de validación, solo tienes que modificarla en un lugar.
Dependencias para formateo de respuestas
Otra aplicación práctica es crear dependencias que preparen datos de forma consistente para tus respuestas:
def obtener_metadatos_respuesta():
from datetime import datetime
return {
"timestamp": datetime.now().isoformat(),
"servidor": "api-v1",
"zona_horaria": "UTC"
}
def formatear_respuesta_exitosa(datos: dict, metadatos: dict = Depends(obtener_metadatos_respuesta)):
return {
"exito": True,
"datos": datos,
"metadatos": metadatos
}
@app.get("/estadisticas")
def obtener_estadisticas(respuesta_base: dict = Depends(formatear_respuesta_exitosa)):
estadisticas = {"usuarios_activos": 150, "productos_vendidos": 1200}
respuesta_base["datos"] = estadisticas
return respuesta_base
Dependencias con lógica de negocio
Las dependencias también pueden encapsular reglas de negocio específicas de tu aplicación:
def calcular_descuento_usuario(tipo_usuario: str = "regular"):
descuentos = {
"premium": 0.15,
"vip": 0.25,
"regular": 0.05
}
descuento = descuentos.get(tipo_usuario, 0.05)
return {"tipo": tipo_usuario, "descuento": descuento}
@app.get("/precio/{producto_id}")
def calcular_precio_final(
producto_id: int,
precio_base: float = 100.0,
descuento_info: dict = Depends(calcular_descuento_usuario)
):
precio_final = precio_base * (1 - descuento_info["descuento"])
return {
"producto_id": producto_id,
"precio_base": precio_base,
"descuento_aplicado": descuento_info["descuento"],
"precio_final": round(precio_final, 2)
}
Combinando múltiples dependencias reutilizables
La verdadera potencia surge cuando combinas varias dependencias reutilizables en una sola ruta:
def obtener_configuracion_cache():
return {"cache_activo": True, "tiempo_expiracion": 300}
def generar_id_peticion():
import uuid
return str(uuid.uuid4())[:8]
@app.get("/reporte/{reporte_id}")
def generar_reporte(
reporte_id: int = Depends(validar_id_positivo),
id_peticion: str = Depends(generar_id_peticion),
config_cache: dict = Depends(obtener_configuracion_cache),
metadatos: dict = Depends(obtener_metadatos_respuesta)
):
return {
"reporte_id": reporte_id,
"id_peticion": id_peticion,
"datos_reporte": f"Contenido del reporte {reporte_id}",
"cache": config_cache,
"metadatos": metadatos
}
Dependencias con parámetros configurables
Para mayor flexibilidad, puedes crear dependencias parametrizables que se adapten a diferentes situaciones:
def crear_validador_rango(minimo: int, maximo: int):
def validar_rango(valor: int):
if valor < minimo or valor > maximo:
raise HTTPException(
status_code=400,
detail=f"El valor debe estar entre {minimo} y {maximo}"
)
return valor
return validar_rango
# Crear validadores específicos
validar_edad = crear_validador_rango(0, 120)
validar_puntuacion = crear_validador_rango(1, 10)
@app.post("/usuario")
def crear_usuario(edad: int = Depends(validar_edad)):
return {"mensaje": "Usuario creado", "edad": edad}
@app.post("/resena")
def crear_resena(puntuacion: int = Depends(validar_puntuacion)):
return {"mensaje": "Reseña creada", "puntuacion": puntuacion}
Organizando dependencias en módulos
A medida que tu API crece, es recomendable organizar las dependencias en archivos separados para mantener el código limpio:
# archivo: dependencias/validaciones.py
from fastapi import HTTPException
def validar_email_formato(email: str):
import re
patron = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
if not re.match(patron, email):
raise HTTPException(status_code=400, detail="Formato de email inválido")
return email.lower()
# archivo: main.py
from fastapi import FastAPI, Depends
from dependencias.validaciones import validar_email_formato
app = FastAPI()
@app.post("/suscripcion")
def crear_suscripcion(email: str = Depends(validar_email_formato)):
return {"mensaje": "Suscripción creada", "email": email}
Las dependencias reutilizables transforman tu código en un conjunto de componentes modulares que puedes combinar de diferentes formas. Esto no solo reduce la duplicación, sino que hace que tu API sea más fácil de mantener, probar y extender a medida que crece.
Aprendizajes de esta lección
- Comprender el concepto y la sintaxis básica de la inyección de dependencias con Depends() en FastAPI
- Aprender a reutilizar funciones de dependencia para validación, formateo y lógica de negocio
- Saber cómo combinar múltiples dependencias en una sola ruta para optimizar el código
- Entender cómo crear dependencias parametrizables y organizarlas en módulos para mantener el código limpio
- Reconocer las ventajas de la inyección de dependencias en términos de reutilización, mantenibilidad y testabilidad
Completa FastAPI y certifícate
Únete a nuestra plataforma y accede a miles de tutoriales, ejercicios prácticos, proyectos reales y nuestro asistente de IA personalizado para acelerar tu aprendizaje.
Asistente IA
Resuelve dudas al instante
Ejercicios
Practica con proyectos reales
Certificados
Valida tus conocimientos
Más de 25.000 desarrolladores ya se han certificado con CertiDevs