FastAPI Inyección de Dependencias
FastAPI proporciona un sistema de inyección de dependencias potente y sencillo.
La inyección de dependencias es un patrón de diseño que te permite extraer lógica común (como conexiones de base de datos, autenticación, validación de parámetros, etc.) en componentes reutilizables y luego usarlos según sea necesario en las rutas.

¿Qué es la inyección de dependencias?
En pocas palabras,una dependenciaes una función que puede usar los mismos parámetros que las funciones de operación de ruta (parámetros de consulta, parámetros de ruta, cuerpo de la solicitud, etc.). FastAPI llama automáticamente a la función de dependencia antes de ejecutar la función de ruta y pasa su valor de retorno a la función de ruta.
Ejemplo
from fastapi import Depends, FastAPI
app = FastAPI()
# 1. Definir la función de dependencia
def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
return {"q": q, "skip": skip, "limit": limit}
# 2. Usar la dependencia en la ruta
@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):
# commons recibe el valor de retorno de la función de dependencia
return commons
@app.get("/users/")
async def read_users(commons: dict = Depends(common_parameters)):
# Varias rutas pueden reutilizar la misma dependencia
return commons
Explicación del código:
| Parte | Descripción |
|---|---|
common_parameters | Función de dependencia, maneja parámetros de consulta comunes |
Depends(common_parameters) | Declarar parámetrocommonsel valor proviene de la función de dependencia |
commons: dict | Recibe el diccionario devuelto por la función de dependencia |
Las funciones de dependencia y las funciones de operación de ruta usan la misma forma de declarar parámetros. FastAPI resuelve automáticamente los parámetros de la función de dependencia. Esto significa que la función de dependencia también puede usar parámetros de consulta, parámetros de ruta, cuerpo de la solicitud, etc.
Flujo de ejecución de dependencias
Cuando llega una solicitud, el orden de procesamiento de FastAPI:
- Identificar la función de ruta y sus dependencias
- Ejecutar las funciones de dependencia (en orden de dependencia)
- Pasar los valores de retorno de las funciones de dependencia a la función de ruta
- Ejecutar la función de ruta
Clases como dependencias
Además de funciones, también puedes usar clases como dependencias:
Ejemplo
from fastapi import Depends, FastAPI
app = FastAPI()
# Declarar dependencia con una clase
class CommonQueryParams:
def __init__(self, q: str | None = None, skip: int = 0, limit: int = 100):
self.q = q
self.skip = skip
self.limit = limit
# Usar la clase como dependencia
@app.get("/items/")
async def read_items(commons: Annotated[CommonQueryParams, Depends()]):
return {"q": commons.q, "skip": commons.skip, "limit": commons.limit}
CuandoDepends()Cuando no se pasa un parámetro, FastAPI usa automáticamente la anotación de tipo del parámetro (CommonQueryParams) como dependencia.
Sub-dependencias
Las dependencias pueden tener sus propias dependencias, formando una cadena de dependencias:
Ejemplo
from fastapi import Depends, FastAPI
app = FastAPI()
# Función de dependencia
def query_extractor(q: str | None = None):
return q
# Sub-dependencia: depende de query_extractor
def query_checker(q: str = Depends(query_extractor)):
if q == "admin":
# La sub-dependencia puede realizar validación
return q + " (checked)"
return q
# La ruta usa la sub-dependencia
@app.get("/items/")
async def read_items(q: str = Depends(query_checker)):
return {"q": q}
Flujo de ejecución:query_extractor -> query_checker-> Función de ruta
Usar dependencias en decoradores
A veces solo necesitas los efectos secundarios de la dependencia (como verificación de permisos), no su valor de retorno. Puedes declararlo en el parámetrodependenciesdel decorador:
Ejemplo
app = FastAPI()
# Dependencia: validar API Key
async def verify_api_key(x_api_key: str = Header()):
if x_api_key != "secret-key":
raise HTTPException(status_code=400, detail="X-API-Key invalid")
# Usar la dependencia en el decorador, sin necesidad de valor de retorno
@app.get("/items/", dependencies=[Depends(verify_api_key)])
async def read_items():
return [{"item": "Foo"}]
# Usar la dependencia para todo el grupo de rutas
@app.get("/users/", dependencies=[Depends(verify_api_key)])
async def read_users():
return [{"user": "Bar"}]
Dependencias globales
Se puedenFastAPIdeclarar dependencias globales en la instancia, que se aplican a todas las rutas:
Ejemplo
async def verify_token(x_token: str = Header()):
if x_token != "fake-super-secret-token":
raise HTTPException(status_code=400, detail="X-Token header invalid")
# Dependencia global: todas las rutas requieren validación de token
app = FastAPI(dependencies=[Depends(verify_token)])
@app.get("/items/")
async def read_items():
return [{"item": "Foo"}]
@app.get("/users/")
async def read_users():
return [{"user": "Bar"}]
Dependencias con yield
Cuando la dependencia necesita realizar operaciones de limpieza (como cerrar la conexión de la base de datos), usayield:
Ejemplo
from fastapi import Depends, FastAPI
app = FastAPI()
# Dependencia con yield: crea la conexión antes de la solicitud, la cierra después de la solicitud
def get_db():
db = "database_connection" # Simular la creación de una conexión de base de datos
try:
yield db # Proporcionar la conexión de base de datos durante el procesamiento de la solicitud
finally:
print("Cerrar la conexión de base de datos") # Limpiar recursos después de completar la solicitud
@app.get("/items/")
async def read_items(db: str = Depends(get_db)):
return {"db": db}
Flujo de ejecución:
- Cuando llega la solicitud, se ejecuta
yieldel código anterior, creando la conexión de base de datos yieldSe pasa la conexión a la función de ruta- Después de que la función de ruta termina de ejecutarse, se ejecuta
finallyel código de limpieza en el bloque
yieldLas dependencias son muy adecuadas para gestionar recursos que necesitan limpieza, como conexiones de base de datos, manejadores de archivos, etc. Independientemente de si la función de ruta lanza una excepción, el código de limpieza se ejecutará.
Resumen
- La inyección de dependencias extrae lógica común en funciones o clases reutilizables
- Usar
Depends()para declarar dependencias en los parámetros de la función de ruta - Las dependencias pueden anidarse, formando cadenas de dependencias
- El parámetro
dependenciesdel decorador se usa para dependencias que no necesitan valor de retorno - Las dependencias que usan
yieldadmiten la limpieza de recursos - Las dependencias globales se aplican a todas las rutas