Handling multiple connections in Flask API
I am writing a simple internal REST API for our solution using Flask, serving JSON objects through calls (including authentication). We have several backends for fetching data. From what I understand, they should be associated with a function decorated @app.before_request
and assigned globally g
for use in the specific requested route. This is not a template that I am used to.
Here's an example of a game I'm making:
@app.before_request
def before_request():
g.some_conn_a = create_connection('a')
g.some_conn_b = create_connection('b')
g.some_client = create_client()
@app.route('/get_some_data')
@requires_auth
def get_some_data():
# Fetch something from all connections in g
payload = ... # Construct payload using above connections
return jsonify(payload)
@app.route('/get_some_other_data')
@requires_auth
def get_some_other_data():
# Fetch something from maybe just g.some_conn_b
payload = ... # Construct payload using g.some_conn_b
return jsonify(payload)
It seems wasteful to me if the user makes a request for data that is only in one or two of these connections / clients, such as in the example route get_some_other_data
.
I am considering just making connections / clients in route functions or loading them lazily. What's the "correct" way? I hope this is not a new module that seems extreme for what I am doing.
source to share
Riffing on example checkbox docs Database Connections you can modify get_db () to accept an argument for each of your multiple connections.
def get_db(conn):
"""Open specificied connection if none yet for the current app context. """
if conn == 'some_conn_a':
if not hasattr(g, 'some_conn_a'):
g.some_conn_a = create_connection('a')
db = g.some_conn_a
elif conn == 'some_conn_b':
if not hasattr(g, 'some_conn_b'):
g.some_conn_b = create_connection('b')
db = g.some_conn_b
elif conn == 'some_client':
if not hasattr(g, 'some_client'):
g.some_client = create_client()
db = g.some_client
else:
raise Exception("Unknown connection: %s" % conn)
return db
@app.teardown_appcontext
def close_db(error):
"""Closes the db connections. """
if hasattr(g, 'some_conn_a'):
g.some_conn_a.close()
if hasattr(g, 'some_conn_b'):
g.some_conn_b.close()
if hasattr(g, 'some_client'):
g.some_client.close()
Then you can query each connection as needed:
@app.route('/get_some_data')
def get_some_data():
data_a = get_db('some_conn_a').query().something()
data_b = get_db('some_conn_b').query().something()
data_c = get_db('some_client').query().something()
payload = {'a': data_a, 'b': data_b, 'c': data_c}
return jsonify(payload)
The get_db () pattern is preferred over the before_request pattern for lazy connections to the download database. The sample docs for Flask 0.11 and up use the get_db () pattern to a greater extent.
source to share