Flask: 'Working outside of application context' — qué significa y cómo resolverlo
El error que aparece al usar current_app, db o url_for fuera de una petición. Por qué ocurre y las tres formas de solucionarlo según tu caso.
Estás ejecutando un script, una tarea programada o una prueba, y Flask te lanza esto:
RuntimeError: Working outside of application context.
Es uno de los errores más desconcertantes para quien empieza con Flask, porque el código “debería funcionar”. Vamos a entender por qué pasa y cómo salir.
Por qué ocurre
Flask mantiene un “contexto de aplicación” que solo existe automáticamente durante una petición HTTP. Objetos como current_app, la sesión, url_for o tu instancia de base de datos dependen de ese contexto para saber a qué aplicación pertenecen.
Cuando usas esos objetos fuera de una petición —en un script suelto, en el arranque, en una tarea de fondo o en un test— ese contexto no existe, y Flask no tiene forma de saber de qué app le hablas. De ahí el error.
Solución 1: crear el contexto manualmente
Es la solución para scripts y tareas. Envuelves el código en app.app_context():
from mi_app import app, db
with app.app_context():
# Aquí dentro sí funciona current_app, db, etc.
usuarios = db.session.query(Usuario).all()
print(usuarios)
Todo lo que va dentro del with tiene contexto. Al salir, se libera. Esta es la respuesta correcta el 90% de las veces.
Solución 2: la factory de aplicación
Si usas el patrón application factory (una función create_app()), crea la instancia y luego el contexto:
from mi_app import create_app, db
app = create_app()
with app.app_context():
db.create_all()
Este es el caso típico al inicializar la base de datos desde un script aparte.
Solución 3: en los tests
Con pytest, lo limpio es un fixture que provee el contexto a todas las pruebas:
import pytest
from mi_app import create_app, db
@pytest.fixture
def app():
app = create_app()
with app.app_context():
db.create_all()
yield app
db.session.remove()
db.drop_all()
La regla para recordarlo
Si un objeto de Flask necesita saber “¿de qué aplicación estamos hablando?” y no estás dentro de una petición, tienes que decírselo tú con app.app_context(). Ese es todo el misterio.
¿Te apareció este error en un contexto distinto —Celery, un hilo, un comando de CLI? Escríbeme desde contacto y lo añadimos al artículo.