mirror of https://github.com/mitsuhiko/flask.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
5.4 KiB
159 lines
5.4 KiB
.. currentmodule:: flask |
|
|
|
.. _app-context: |
|
|
|
The Application Context |
|
======================= |
|
|
|
The application context keeps track of the application-level data during |
|
a request, CLI command, or other activity. Rather than passing the |
|
application around to each function, the :data:`current_app` and |
|
:data:`g` proxies are accessed instead. |
|
|
|
This is similar to the :doc:`/reqcontext`, which keeps track of |
|
request-level data during a request. A corresponding application context |
|
is pushed when a request context is pushed. |
|
|
|
Purpose of the Context |
|
---------------------- |
|
|
|
The :class:`Flask` application object has attributes, such as |
|
:attr:`~Flask.config`, that are useful to access within views and |
|
:doc:`CLI commands </cli>`. However, importing the ``app`` instance |
|
within the modules in your project is prone to circular import issues. |
|
When using the :doc:`app factory pattern </patterns/appfactories>` or |
|
writing reusable :doc:`blueprints </blueprints>` or |
|
:doc:`extensions </extensions>` there won't be an ``app`` instance to |
|
import at all. |
|
|
|
Flask solves this issue with the *application context*. Rather than |
|
referring to an ``app`` directly, you use the the :data:`current_app` |
|
proxy, which points to the application handling the current activity. |
|
|
|
Flask automatically *pushes* an application context when handling a |
|
request. View functions, error handlers, and other functions that run |
|
during a request will have access to :data:`current_app`. |
|
|
|
Flask will also automatically push an app context when running CLI |
|
commands registered with :attr:`Flask.cli` using ``@app.cli.command()``. |
|
|
|
|
|
Lifetime of the Context |
|
----------------------- |
|
|
|
The application context is created and destroyed as necessary. When a |
|
Flask application begins handling a request, it pushes an application |
|
context and a :doc:`request context </reqcontext>`. When the request |
|
ends it pops the request context then the application context. |
|
Typically, an application context will have the same lifetime as a |
|
request. |
|
|
|
See :doc:`/reqcontext` for more information about how the contexts work |
|
and the full lifecycle of a request. |
|
|
|
|
|
Manually Push a Context |
|
----------------------- |
|
|
|
If you try to access :data:`current_app`, or anything that uses it, |
|
outside an application context, you'll get this error message: |
|
|
|
.. code-block:: pytb |
|
|
|
RuntimeError: Working outside of application context. |
|
|
|
This typically means that you attempted to use functionality that |
|
needed to interface with the current application object in some way. |
|
To solve this, set up an application context with app.app_context(). |
|
|
|
If you see that error while configuring your application, such as when |
|
initializing an extension, you can push a context manually since you |
|
have direct access to the ``app``. Use :meth:`~Flask.app_context` in a |
|
``with`` block, and everything that runs in the block will have access |
|
to :data:`current_app`. :: |
|
|
|
def create_app(): |
|
app = Flask(__name__) |
|
|
|
with app.app_context(): |
|
init_db() |
|
|
|
return app |
|
|
|
If you see that error somewhere else in your code not related to |
|
configuring the application, it most likely indicates that you should |
|
move that code into a view function or CLI command. |
|
|
|
|
|
Storing Data |
|
------------ |
|
|
|
The application context is a good place to store common data during a |
|
request or CLI command. Flask provides the :data:`g object <g>` for this |
|
purpose. It is a simple namespace object that has the same lifetime as |
|
an application context. |
|
|
|
.. note:: |
|
The ``g`` name stands for "global", but that is referring to the |
|
data being global *within a context*. The data on ``g`` is lost |
|
after the context ends, and it is not an appropriate place to store |
|
data between requests. Use the :data:`session` or a database to |
|
store data across requests. |
|
|
|
A common use for :data:`g` is to manage resources during a request. |
|
|
|
1. ``get_X()`` creates resource ``X`` if it does not exist, caching it |
|
as ``g.X``. |
|
2. ``teardown_X()`` closes or otherwise deallocates the resource if it |
|
exists. It is registered as a :meth:`~Flask.teardown_appcontext` |
|
handler. |
|
|
|
For example, you can manage a database connection using this pattern:: |
|
|
|
from flask import g |
|
|
|
def get_db(): |
|
if 'db' not in g: |
|
g.db = connect_to_database() |
|
|
|
return g.db |
|
|
|
@app.teardown_appcontext |
|
def teardown_db(): |
|
db = g.pop('db', None) |
|
|
|
if db is not None: |
|
db.close() |
|
|
|
During a request, every call to ``get_db()`` will return the same |
|
connection, and it will be closed automatically at the end of the |
|
request. |
|
|
|
You can use :class:`~werkzeug.local.LocalProxy` to make a new context |
|
local from ``get_db()``:: |
|
|
|
from werkzeug.local import LocalProxy |
|
db = LocalProxy(get_db) |
|
|
|
Accessing ``db`` will call ``get_db`` internally, in the same way that |
|
:data:`current_app` works. |
|
|
|
---- |
|
|
|
If you're writing an extension, :data:`g` should be reserved for user |
|
code. You may store internal data on the context itself, but be sure to |
|
use a sufficiently unique name. The current context is accessed with |
|
:data:`_app_ctx_stack.top <_app_ctx_stack>`. For more information see |
|
:doc:`extensiondev`. |
|
|
|
|
|
Events and Signals |
|
------------------ |
|
|
|
The application will call functions registered with |
|
:meth:`~Flask.teardown_appcontext` when the application context is |
|
popped. |
|
|
|
If :data:`~signals.signals_available` is true, the following signals are |
|
sent: :data:`appcontext_pushed`, :data:`appcontext_tearing_down`, and |
|
:data:`appcontext_popped`.
|
|
|