Handling Flask application context for slack_bolt

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()

Further Reading

Development #flask #slack #python