From ctx.py:260-298, the AppContext class provides:
Access to current_app and g proxies
Application configuration and resources
Per-request or per-command isolated state
class AppContext: """An app context contains information about an app, and about the request when handling a request. A context is pushed at the beginning of each request and CLI command, and popped at the end.""" def __init__(self, app, *, request=None, session=None): self.app = app self.g = app.app_ctx_globals_class() self.url_adapter = None # ...
# Don't do this in reusable codefrom myapp import appdef some_function(): return app.config['SECRET_KEY']# Do this insteadfrom flask import current_appdef some_function(): return current_app.config['SECRET_KEY']
From ctx.py:30-116, g is a namespace object for storing data during a context:
from flask import g@app.before_requestdef load_user(): # Store data in g if 'user_id' in session: g.user = User.query.get(session['user_id']) else: g.user = None@app.route('/dashboard')def dashboard(): # Access data from g if g.user is None: return redirect(url_for('login')) return f'Welcome, {g.user.name}!'@app.route('/api/data')def api_data(): # Check if attribute exists if hasattr(g, 'user'): return jsonify({'user': g.user.name}) # Or use get() with default user = g.get('user', None) return jsonify({'user': user})
app = Flask(__name__)# Using with statementwith app.app_context(): # Context is active print(current_app.name) g.temp_data = 'value' db.create_all()# Context is popped, g is cleaned up# Using push/popctx = app.app_context()ctx.push()try: # Do work print(current_app.name)finally: ctx.pop()
def push(self): """Push this context so that it is the active context.""" self._push_count += 1 if self._cv_token is not None: return # Already pushed self._cv_token = _cv_app.set(self) appcontext_pushed.send(self.app, _async_wrapper=self.app.ensure_sync)def pop(self, exc=None): """Pop this context and call teardown functions.""" self._push_count -= 1 if self._push_count > 0: return # Still pushed elsewhere # Run teardown functions self.app.do_teardown_appcontext(self, exc) # Reset context variable _cv_app.reset(self._cv_token) self._cv_token = None appcontext_popped.send(self.app, _async_wrapper=self.app.ensure_sync)
@app.teardown_appcontextdef cleanup(exception=None): # Close database connection db = g.pop('db', None) if db is not None: db.close() # Clean up other resources cache = g.pop('cache', None) if cache is not None: cache.clear()
@app.teardown_appcontextdef handle_db_cleanup(exception): db = g.pop('db', None) if db is not None: if exception is not None: # Error occurred, rollback db.rollback() else: # Success, commit db.commit() db.close()
from flask import has_app_contextdef get_db(): if has_app_context(): if 'db' not in g: g.db = create_database_connection() return g.db return None@app.route('/db-info')def db_info(): if has_app_context(): return 'Context active' return 'No context'
from flask import gdef get_db(): if 'db' not in g: g.db = connect_to_database( current_app.config['DATABASE_URI'] ) return g.db@app.teardown_appcontextdef close_db(error): db = g.pop('db', None) if db is not None: db.close()@app.route('/query')def query(): db = get_db() results = db.execute('SELECT * FROM users').fetchall() return jsonify(results)