If you're using flask-sqlalchemy
with slack_bolt
, you've probably encountered this exception when accessing db
within your Slack requests handlers:
RuntimeError: No application found. Either work inside a view function or push an application context. See http://flask-sqlalchemy.pocoo.org/contexts/.
The db
you define with flask_sqlalchemy
needs access to flask.current_app
. This is available anywhere you import flask
, but as it turns out current_app
isn't a Flask
instance as you might expect. current_app
is an instance of LocalProxy
from the werkzeug
package and it returns the Flask instance for the current context. It gets a bit in-depth here, but Werkzeug implements something called context locals for accessing global variables in a thread-safe way.
With this in mind, we get that exception because slack_bolt
handles Slack requests in a new thread and flask.current_app
isn't bound to a Flask
instance in that thread. The solution is simple - bind flask.current_app
to your Flask app for the handler thread. Flask's documentation describes how to do this here.
In my application I used a middleware since middleware is still executed in the main thread and has access to the Flask app:
def bind_flask_app(context, next):
context['flask_app'] = current_app._get_current_object()
next()
@slack_app.command("/some_slash_command", middleware=[bind_flask_app])
context['flask_app'].app_context().push()