File: appcontext.rst

package info (click to toggle)
flask 1.0.2-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 2,224 kB
  • sloc: python: 8,975; makefile: 55; pascal: 51; sql: 22
file content (159 lines) | stat: -rw-r--r-- 5,499 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
.. 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`.