forked from orbit-oss/flask
merge app and request context
This commit is contained in:
parent
330123258e
commit
c2705ffd9c
36 changed files with 779 additions and 1007 deletions
129
docs/api.rst
129
docs/api.rst
|
|
@ -31,17 +31,15 @@ Incoming Request Data
|
|||
:inherited-members:
|
||||
:exclude-members: json_module
|
||||
|
||||
.. attribute:: request
|
||||
.. data:: request
|
||||
|
||||
To access incoming request data, you can use the global `request`
|
||||
object. Flask parses incoming request data for you and gives you
|
||||
access to it through that global object. Internally Flask makes
|
||||
sure that you always get the correct data for the active thread if you
|
||||
are in a multithreaded environment.
|
||||
A proxy to the request data for the current request, an instance of
|
||||
:class:`.Request`.
|
||||
|
||||
This is a proxy. See :ref:`notes-on-proxies` for more information.
|
||||
This is only available when a :doc:`request context </appcontext>` is
|
||||
active.
|
||||
|
||||
The request object is an instance of a :class:`~flask.Request`.
|
||||
This is a proxy. See :ref:`context-visibility` for more information.
|
||||
|
||||
|
||||
Response Objects
|
||||
|
|
@ -62,40 +60,33 @@ does this is by using a signed cookie. The user can look at the session
|
|||
contents, but can't modify it unless they know the secret key, so make sure to
|
||||
set that to something complex and unguessable.
|
||||
|
||||
To access the current session you can use the :class:`session` object:
|
||||
To access the current session you can use the :data:`.session` proxy.
|
||||
|
||||
.. class:: session
|
||||
.. data:: session
|
||||
|
||||
The session object works pretty much like an ordinary dict, with the
|
||||
difference that it keeps track of modifications.
|
||||
A proxy to the session data for the current request, an instance of
|
||||
:class:`.SessionMixin`.
|
||||
|
||||
This is a proxy. See :ref:`notes-on-proxies` for more information.
|
||||
This is only available when a :doc:`request context </appcontext>` is
|
||||
active.
|
||||
|
||||
The following attributes are interesting:
|
||||
This is a proxy. See :ref:`context-visibility` for more information.
|
||||
|
||||
.. attribute:: new
|
||||
The session object works like a dict but tracks assignment and access to its
|
||||
keys. It cannot track modifications to mutable values, you need to set
|
||||
:attr:`~.SessionMixin.modified` manually when modifying a list, dict, etc.
|
||||
|
||||
``True`` if the session is new, ``False`` otherwise.
|
||||
.. code-block:: python
|
||||
|
||||
.. attribute:: modified
|
||||
|
||||
``True`` if the session object detected a modification. Be advised
|
||||
that modifications on mutable structures are not picked up
|
||||
automatically, in that situation you have to explicitly set the
|
||||
attribute to ``True`` yourself. Here an example::
|
||||
|
||||
# this change is not picked up because a mutable object (here
|
||||
# a list) is changed.
|
||||
session['objects'].append(42)
|
||||
# appending to a list is not detected
|
||||
session["numbers"].append(42)
|
||||
# so mark it as modified yourself
|
||||
session.modified = True
|
||||
|
||||
.. attribute:: permanent
|
||||
|
||||
If set to ``True`` the session lives for
|
||||
:attr:`~flask.Flask.permanent_session_lifetime` seconds. The
|
||||
default is 31 days. If set to ``False`` (which is the default) the
|
||||
session will be deleted when the user closes the browser.
|
||||
The session is persisted across requests using a cookie. By default the
|
||||
users's browser will clear the cookie when it is closed. Set
|
||||
:attr:`~.SessionMixin.permanent` to ``True`` to persist the cookie for
|
||||
:data:`PERMANENT_SESSION_LIFETIME`.
|
||||
|
||||
|
||||
Session Interface
|
||||
|
|
@ -158,20 +149,21 @@ another, a global variable is not good enough because it would break in
|
|||
threaded environments. Flask provides you with a special object that
|
||||
ensures it is only valid for the active request and that will return
|
||||
different values for each request. In a nutshell: it does the right
|
||||
thing, like it does for :class:`request` and :class:`session`.
|
||||
thing, like it does for :data:`.request` and :data:`.session`.
|
||||
|
||||
.. data:: g
|
||||
|
||||
A namespace object that can store data during an
|
||||
:doc:`application context </appcontext>`. This is an instance of
|
||||
:attr:`Flask.app_ctx_globals_class`, which defaults to
|
||||
:class:`ctx._AppCtxGlobals`.
|
||||
A proxy to a namespace object used to store data during a single request or
|
||||
app context. An instance of :attr:`.Flask.app_ctx_globals_class`, which
|
||||
defaults to :class:`._AppCtxGlobals`.
|
||||
|
||||
This is a good place to store resources during a request. For
|
||||
example, a ``before_request`` function could load a user object from
|
||||
a session id, then set ``g.user`` to be used in the view function.
|
||||
This is a good place to store resources during a request. For example, a
|
||||
:meth:`~.Flask.before_request` function could load a user object from a
|
||||
session id, then set ``g.user`` to be used in the view function.
|
||||
|
||||
This is a proxy. See :ref:`notes-on-proxies` for more information.
|
||||
This is only available when an :doc:`app context </appcontext>` is active.
|
||||
|
||||
This is a proxy. See :ref:`context-visibility` for more information.
|
||||
|
||||
.. versionchanged:: 0.10
|
||||
Bound to the application context instead of the request context.
|
||||
|
|
@ -185,17 +177,16 @@ Useful Functions and Classes
|
|||
|
||||
.. data:: current_app
|
||||
|
||||
A proxy to the application handling the current request. This is
|
||||
useful to access the application without needing to import it, or if
|
||||
it can't be imported, such as when using the application factory
|
||||
pattern or in blueprints and extensions.
|
||||
A proxy to the :class:`.Flask` application handling the current request or
|
||||
other activity.
|
||||
|
||||
This is only available when an
|
||||
:doc:`application context </appcontext>` is pushed. This happens
|
||||
automatically during requests and CLI commands. It can be controlled
|
||||
manually with :meth:`~flask.Flask.app_context`.
|
||||
This is useful to access the application without needing to import it, or if
|
||||
it can't be imported, such as when using the application factory pattern or
|
||||
in blueprints and extensions.
|
||||
|
||||
This is a proxy. See :ref:`notes-on-proxies` for more information.
|
||||
This is only available when an :doc:`app context </appcontext>` is active.
|
||||
|
||||
This is a proxy. See :ref:`context-visibility` for more information.
|
||||
|
||||
.. autofunction:: has_request_context
|
||||
|
||||
|
|
@ -299,31 +290,31 @@ Stream Helpers
|
|||
Useful Internals
|
||||
----------------
|
||||
|
||||
.. autoclass:: flask.ctx.RequestContext
|
||||
:members:
|
||||
|
||||
.. data:: flask.globals.request_ctx
|
||||
|
||||
The current :class:`~flask.ctx.RequestContext`. If a request context
|
||||
is not active, accessing attributes on this proxy will raise a
|
||||
``RuntimeError``.
|
||||
|
||||
This is an internal object that is essential to how Flask handles
|
||||
requests. Accessing this should not be needed in most cases. Most
|
||||
likely you want :data:`request` and :data:`session` instead.
|
||||
|
||||
.. autoclass:: flask.ctx.AppContext
|
||||
:members:
|
||||
|
||||
.. data:: flask.globals.app_ctx
|
||||
|
||||
The current :class:`~flask.ctx.AppContext`. If an app context is not
|
||||
active, accessing attributes on this proxy will raise a
|
||||
``RuntimeError``.
|
||||
A proxy to the active :class:`.AppContext`.
|
||||
|
||||
This is an internal object that is essential to how Flask handles
|
||||
requests. Accessing this should not be needed in most cases. Most
|
||||
likely you want :data:`current_app` and :data:`g` instead.
|
||||
This is an internal object that is essential to how Flask handles requests.
|
||||
Accessing this should not be needed in most cases. Most likely you want
|
||||
:data:`.current_app`, :data:`.g`, :data:`.request`, and :data:`.session` instead.
|
||||
|
||||
This is only available when a :doc:`request context </appcontext>` is
|
||||
active.
|
||||
|
||||
This is a proxy. See :ref:`context-visibility` for more information.
|
||||
|
||||
.. class:: flask.ctx.RequestContext
|
||||
|
||||
.. deprecated:: 3.2
|
||||
Merged with :class:`AppContext`. This alias will be removed in Flask 4.0.
|
||||
|
||||
.. data:: flask.globals.request_ctx
|
||||
|
||||
.. deprecated:: 3.2
|
||||
Merged with :data:`.app_ctx`. This alias will be removed in Flask 4.0.
|
||||
|
||||
.. autoclass:: flask.blueprints.BlueprintSetupState
|
||||
:members:
|
||||
|
|
|
|||
|
|
@ -1,74 +1,63 @@
|
|||
.. currentmodule:: flask
|
||||
The App and Request Context
|
||||
===========================
|
||||
|
||||
The Application Context
|
||||
=======================
|
||||
The context keeps track of data and objects during a request, CLI command, or
|
||||
other activity. Rather than passing this data around to every function, the
|
||||
:data:`.current_app`, :data:`.g`, :data:`.request`, and :data:`.session` proxies
|
||||
are accessed instead.
|
||||
|
||||
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.
|
||||
When handling a request, the context is referred to as the "request context"
|
||||
because it contains request data in addition to application data. Otherwise,
|
||||
such as during a CLI command, it is referred to as the "app context". During an
|
||||
app context, :data:`.current_app` and :data:`.g` are available, while during a
|
||||
request context :data:`.request` and :data:`.session` are also available.
|
||||
|
||||
This is similar to :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.
|
||||
The context and proxies help solve two development issues: circular imports, and
|
||||
passing around global data during a request.
|
||||
|
||||
Flask solves this issue with the *application context*. Rather than
|
||||
referring to an ``app`` directly, you use the :data:`current_app`
|
||||
proxy, which points to the application handling the current activity.
|
||||
The :class:`.Flask` application object has attributes, such as
|
||||
:attr:`~.Flask.config`, that are useful to access within views and other
|
||||
functions. 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 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`.
|
||||
When the application handles a request, it creates a :class:`.Request` object.
|
||||
Because a *worker* handles only one request at a time, the request data can be
|
||||
considered global to that worker during that request. Passing it as an argument
|
||||
through every function during the request becomes verbose and redundant.
|
||||
|
||||
Flask will also automatically push an app context when running CLI
|
||||
commands registered with :attr:`Flask.cli` using ``@app.cli.command()``.
|
||||
Flask solves these issues with the *active context* pattern. Rather than
|
||||
importing an ``app`` directly, or having to pass it and the request through to
|
||||
every single function, you import and access the proxies, which point to the
|
||||
currently active application and request data. This is sometimes referred to
|
||||
as "context local" data.
|
||||
|
||||
|
||||
Lifetime of the Context
|
||||
-----------------------
|
||||
Context During Setup
|
||||
--------------------
|
||||
|
||||
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 life cycle 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:
|
||||
If you try to access :data:`.current_app`, :data:`.g`, or anything that uses it,
|
||||
outside an app 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().
|
||||
Attempted to use functionality that expected a current application to be
|
||||
set. To solve this, set up an app context using 'with app.app_context()'.
|
||||
See the documentation on app context for more information.
|
||||
|
||||
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`. ::
|
||||
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.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def create_app():
|
||||
app = Flask(__name__)
|
||||
|
|
@ -78,70 +67,120 @@ to :data:`current_app`. ::
|
|||
|
||||
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.
|
||||
If you see that error somewhere else in your code not related to setting up the
|
||||
application, it most likely indicates that you should move that code into a view
|
||||
function or CLI command.
|
||||
|
||||
|
||||
Storing Data
|
||||
------------
|
||||
Context During Testing
|
||||
----------------------
|
||||
|
||||
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.
|
||||
See :doc:`/testing` for detailed information about managing the context during
|
||||
tests.
|
||||
|
||||
.. 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.
|
||||
If you try to access :data:`.request`, :data:`.session`, or anything that uses
|
||||
it, outside a request context, you'll get this error message:
|
||||
|
||||
A common use for :data:`g` is to manage resources during a request.
|
||||
.. code-block:: pytb
|
||||
|
||||
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.
|
||||
RuntimeError: Working outside of request context.
|
||||
|
||||
For example, you can manage a database connection using this pattern::
|
||||
Attempted to use functionality that expected an active HTTP request. See the
|
||||
documentation on request context for more information.
|
||||
|
||||
from flask import g
|
||||
This will probably only happen during tests. If you see that error somewhere
|
||||
else in your code not related to testing, it most likely indicates that you
|
||||
should move that code into a view function.
|
||||
|
||||
def get_db():
|
||||
if 'db' not in g:
|
||||
g.db = connect_to_database()
|
||||
The primary way to solve this is to use :meth:`.Flask.test_client` to simulate
|
||||
a full request.
|
||||
|
||||
return g.db
|
||||
If you only want to unit test one function, rather than a full request, use
|
||||
:meth:`.Flask.test_request_context` in a ``with`` block.
|
||||
|
||||
@app.teardown_appcontext
|
||||
def teardown_db(exception):
|
||||
db = g.pop('db', None)
|
||||
.. code-block:: python
|
||||
|
||||
if db is not None:
|
||||
db.close()
|
||||
def generate_report(year):
|
||||
format = request.args.get("format")
|
||||
...
|
||||
|
||||
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.
|
||||
with app.test_request_context(
|
||||
"/make_report/2017", query_string={"format": "short"}
|
||||
):
|
||||
generate_report()
|
||||
|
||||
|
||||
Events and Signals
|
||||
------------------
|
||||
.. _context-visibility:
|
||||
|
||||
The application will call functions registered with :meth:`~Flask.teardown_appcontext`
|
||||
when the application context is popped.
|
||||
Visibility of the Context
|
||||
-------------------------
|
||||
|
||||
The following signals are sent: :data:`appcontext_pushed`,
|
||||
:data:`appcontext_tearing_down`, and :data:`appcontext_popped`.
|
||||
The context will have the same lifetime as an activity, such as a request, CLI
|
||||
command, or ``with`` block. Various callbacks and signals registered with the
|
||||
app will be run during the context.
|
||||
|
||||
When a Flask application handles a request, it pushes a requet context
|
||||
to set the active application and request data. When it handles a CLI command,
|
||||
it pushes an app context to set the active application. When the activity ends,
|
||||
it pops that context. Proxy objects like :data:`.request`, :data:`.session`,
|
||||
:data:`.g`, and :data:`.current_app`, are accessible while the context is pushed
|
||||
and active, and are not accessible after the context is popped.
|
||||
|
||||
The context is unique to each thread (or other worker type). The proxies cannot
|
||||
be passed to another worker, which has a different context space and will not
|
||||
know about the active context in the parent's space.
|
||||
|
||||
Besides being scoped to each worker, the proxy object has a separate type and
|
||||
identity than the proxied real object. In some cases you'll need access to the
|
||||
real object, rather than the proxy. Use the
|
||||
:meth:`~.LocalProxy._get_current_object` method in those cases.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
app = current_app._get_current_object()
|
||||
my_signal.send(app)
|
||||
|
||||
|
||||
Lifcycle of the Context
|
||||
-----------------------
|
||||
|
||||
Flask dispatches a request in multiple stages which can affect the request,
|
||||
response, and how errors are handled. See :doc:`/lifecycle` for a list of all
|
||||
the steps, callbacks, and signals during each request. The following are the
|
||||
steps directly related to the context.
|
||||
|
||||
- The app context is pushed, the proxies are available.
|
||||
- The :data:`.appcontext_pushed` signal is sent.
|
||||
- The request is dispatched.
|
||||
- Any :meth:`.Flask.teardown_request` decorated functions are called.
|
||||
- The :data:`.request_tearing_down` signal is sent.
|
||||
- Any :meth:`.Flask.teardown_appcontext` decorated functions are called.
|
||||
- The :data:`.appcontext_tearing_down` signal is sent.
|
||||
- The app context is popped, the proxies are no longer available.
|
||||
- The :data:`.appcontext_popped` signal is sent.
|
||||
|
||||
The teardown callbacks are called by the context when it is popped. They are
|
||||
called even if there is an unhandled exception during dispatch. They may be
|
||||
called multiple times in some test scenarios. This means there is no guarantee
|
||||
that any other parts of the request dispatch have run. Be sure to write these
|
||||
functions in a way that does not depend on other callbacks and will not fail.
|
||||
|
||||
|
||||
How the Context Works
|
||||
---------------------
|
||||
|
||||
Context locals are implemented using Python's :mod:`contextvars` and Werkzeug's
|
||||
:class:`~werkzeug.local.LocalProxy`. Python's contextvars are a low level
|
||||
structure to manage data local to a thread or coroutine. ``LocalProxy`` wraps
|
||||
the contextvar so that access to any attributes and methods is forwarded to the
|
||||
object stored in the contextvar.
|
||||
|
||||
The context is tracked like a stack, with the active context at the top of the
|
||||
stack. Flask manages pushing and popping contexts during requests, CLI commands,
|
||||
testing, ``with`` blocks, etc. The proxies access attributes on the active
|
||||
context.
|
||||
|
||||
Because it is a stack, other contexts may be pushed to change the proxies during
|
||||
an already active context. This is not a common pattern, but can be used in
|
||||
advanced use cases. For example, a Flask application can be used as WSGI
|
||||
middleware, calling another wrapped Flask app from a view.
|
||||
|
|
|
|||
|
|
@ -169,19 +169,20 @@ infrastructure, packages with dependencies are no longer an issue and
|
|||
there are very few reasons against having libraries that depend on others.
|
||||
|
||||
|
||||
Thread Locals
|
||||
-------------
|
||||
Context Locals
|
||||
--------------
|
||||
|
||||
Flask uses thread local objects (context local objects in fact, they
|
||||
support greenlet contexts as well) for request, session and an extra
|
||||
object you can put your own things on (:data:`~flask.g`). Why is that and
|
||||
isn't that a bad idea?
|
||||
Flask uses special context locals and proxies to provide access to the
|
||||
current app and request data to any code running during a request, CLI command,
|
||||
etc. Context locals are specific to the worker handling the activity, such as a
|
||||
thread, process, coroutine, or greenlet.
|
||||
|
||||
Yes it is usually not such a bright idea to use thread locals. They cause
|
||||
troubles for servers that are not based on the concept of threads and make
|
||||
large applications harder to maintain. However Flask is just not designed
|
||||
for large applications or asynchronous servers. Flask wants to make it
|
||||
quick and easy to write a traditional web application.
|
||||
The context and proxies help solve two development issues: circular imports, and
|
||||
passing around global data. :data:`.current_app: can be used to access the
|
||||
application object without needing to import the app object directly, avoiding
|
||||
circular import issues. :data:`.request`, :data:`.session`, and :data`.g` can be
|
||||
imported to access the current data for the request, rather than needing to
|
||||
pass them as arguments through every single function in your project.
|
||||
|
||||
|
||||
Async/await and ASGI support
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ application instance.
|
|||
It is important that the app is not stored on the extension, don't do
|
||||
``self.app = app``. The only time the extension should have direct
|
||||
access to an app is during ``init_app``, otherwise it should use
|
||||
:data:`current_app`.
|
||||
:data:`.current_app`.
|
||||
|
||||
This allows the extension to support the application factory pattern,
|
||||
avoids circular import issues when importing the extension instance
|
||||
|
|
@ -105,7 +105,7 @@ during an extension's ``init_app`` method.
|
|||
A common pattern is to use :meth:`~Flask.before_request` to initialize
|
||||
some data or a connection at the beginning of each request, then
|
||||
:meth:`~Flask.teardown_request` to clean it up at the end. This can be
|
||||
stored on :data:`g`, discussed more below.
|
||||
stored on :data:`.g`, discussed more below.
|
||||
|
||||
A more lazy approach is to provide a method that initializes and caches
|
||||
the data or connection. For example, a ``ext.get_db`` method could
|
||||
|
|
@ -179,13 +179,12 @@ name as a prefix, or as a namespace.
|
|||
g._hello = SimpleNamespace()
|
||||
g._hello.user_id = 2
|
||||
|
||||
The data in ``g`` lasts for an application context. An application
|
||||
context is active when a request context is, or when a CLI command is
|
||||
run. If you're storing something that should be closed, use
|
||||
:meth:`~flask.Flask.teardown_appcontext` to ensure that it gets closed
|
||||
when the application context ends. If it should only be valid during a
|
||||
request, or would not be used in the CLI outside a request, use
|
||||
:meth:`~flask.Flask.teardown_request`.
|
||||
The data in ``g`` lasts for an application context. An application context is
|
||||
active during a request, CLI command, or ``with app.app_context()`` block. If
|
||||
you're storing something that should be closed, use
|
||||
:meth:`~flask.Flask.teardown_appcontext` to ensure that it gets closed when the
|
||||
app context ends. If it should only be valid during a request, or would not be
|
||||
used in the CLI outside a request, use :meth:`~flask.Flask.teardown_request`.
|
||||
|
||||
|
||||
Views and Models
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ community-maintained extensions to add even more functionality.
|
|||
views
|
||||
lifecycle
|
||||
appcontext
|
||||
reqcontext
|
||||
blueprints
|
||||
extensions
|
||||
cli
|
||||
|
|
|
|||
|
|
@ -117,15 +117,12 @@ the view function, and pass the return value back to the server. But there are m
|
|||
parts that you can use to customize its behavior.
|
||||
|
||||
#. WSGI server calls the Flask object, which calls :meth:`.Flask.wsgi_app`.
|
||||
#. A :class:`.RequestContext` object is created. This converts the WSGI ``environ``
|
||||
dict into a :class:`.Request` object. It also creates an :class:`AppContext` object.
|
||||
#. The :doc:`app context <appcontext>` is pushed, which makes :data:`.current_app` and
|
||||
:data:`.g` available.
|
||||
#. An :class:`.AppContext` object is created. This converts the WSGI ``environ``
|
||||
dict into a :class:`.Request` object.
|
||||
#. The :doc:`app context <appcontext>` is pushed, which makes
|
||||
:data:`.current_app`, :data:`.g`, :data:`.request`, and :data:`.session`
|
||||
available.
|
||||
#. The :data:`.appcontext_pushed` signal is sent.
|
||||
#. The :doc:`request context <reqcontext>` is pushed, which makes :attr:`.request` and
|
||||
:class:`.session` available.
|
||||
#. The session is opened, loading any existing session data using the app's
|
||||
:attr:`~.Flask.session_interface`, an instance of :class:`.SessionInterface`.
|
||||
#. The URL is matched against the URL rules registered with the :meth:`~.Flask.route`
|
||||
decorator during application setup. If there is no match, the error - usually a 404,
|
||||
405, or redirect - is stored to be handled later.
|
||||
|
|
@ -141,7 +138,8 @@ parts that you can use to customize its behavior.
|
|||
called to handle the error and return a response.
|
||||
#. Whatever returned a response value - a before request function, the view, or an
|
||||
error handler, that value is converted to a :class:`.Response` object.
|
||||
#. Any :func:`~.after_this_request` decorated functions are called, then cleared.
|
||||
#. Any :func:`~.after_this_request` decorated functions are called, which can modify
|
||||
the response object. They are then cleared.
|
||||
#. Any :meth:`~.Flask.after_request` decorated functions are called, which can modify
|
||||
the response object.
|
||||
#. The session is saved, persisting any modified session data using the app's
|
||||
|
|
@ -154,14 +152,19 @@ parts that you can use to customize its behavior.
|
|||
#. The response object's status, headers, and body are returned to the WSGI server.
|
||||
#. Any :meth:`~.Flask.teardown_request` decorated functions are called.
|
||||
#. The :data:`.request_tearing_down` signal is sent.
|
||||
#. The request context is popped, :attr:`.request` and :class:`.session` are no longer
|
||||
available.
|
||||
#. Any :meth:`~.Flask.teardown_appcontext` decorated functions are called.
|
||||
#. The :data:`.appcontext_tearing_down` signal is sent.
|
||||
#. The app context is popped, :data:`.current_app` and :data:`.g` are no longer
|
||||
available.
|
||||
#. The app context is popped, :data:`.current_app`, :data:`.g`, :data:`.request`,
|
||||
and :data:`.session` are no longer available.
|
||||
#. The :data:`.appcontext_popped` signal is sent.
|
||||
|
||||
When executing a CLI command or plain app context without request data, the same
|
||||
order of steps is followed, omitting the steps that refer to the request.
|
||||
|
||||
A :class:`Blueprint` can add handlers for these events that are specific to the
|
||||
blueprint. The handlers for a blueprint will run if the blueprint
|
||||
owns the route that matches the request.
|
||||
|
||||
There are even more decorators and customization points than this, but that aren't part
|
||||
of every request lifecycle. They're more specific to certain things you might use during
|
||||
a request, such as templates, building URLs, or handling JSON data. See the rest of this
|
||||
|
|
|
|||
|
|
@ -131,9 +131,8 @@ Here is an example :file:`database.py` module for your application::
|
|||
def init_db():
|
||||
metadata.create_all(bind=engine)
|
||||
|
||||
As in the declarative approach, you need to close the session after
|
||||
each request or application context shutdown. Put this into your
|
||||
application module::
|
||||
As in the declarative approach, you need to close the session after each app
|
||||
context. Put this into your application module::
|
||||
|
||||
from yourapplication.database import db_session
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
Using SQLite 3 with Flask
|
||||
=========================
|
||||
|
||||
In Flask you can easily implement the opening of database connections on
|
||||
demand and closing them when the context dies (usually at the end of the
|
||||
request).
|
||||
You can implement a few functions to work with a SQLite connection during a
|
||||
request context. The connection is created the first time it's accessed,
|
||||
reused on subsequent access, until it is closed when the request context ends.
|
||||
|
||||
Here is a simple example of how you can use SQLite 3 with Flask::
|
||||
|
||||
|
|
|
|||
|
|
@ -49,13 +49,13 @@ the template.
|
|||
Streaming with Context
|
||||
----------------------
|
||||
|
||||
The :data:`~flask.request` will not be active while the generator is
|
||||
running, because the view has already returned at that point. If you try
|
||||
to access ``request``, you'll get a ``RuntimeError``.
|
||||
The :data:`.request` proxy will not be active while the generator is
|
||||
running, because the app has already returned control to the WSGI server at that
|
||||
point. If you try to access ``request``, you'll get a ``RuntimeError``.
|
||||
|
||||
If your generator function relies on data in ``request``, use the
|
||||
:func:`~flask.stream_with_context` wrapper. This will keep the request
|
||||
context active during the generator.
|
||||
:func:`.stream_with_context` wrapper. This will keep the request context active
|
||||
during the generator.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ Why would you want to build URLs using the URL reversing function
|
|||
For example, here we use the :meth:`~flask.Flask.test_request_context` method
|
||||
to try out :func:`~flask.url_for`. :meth:`~flask.Flask.test_request_context`
|
||||
tells Flask to behave as though it's handling a request even while we use a
|
||||
Python shell. See :ref:`context-locals`.
|
||||
Python shell. See :doc:`/appcontext`.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
|
@ -449,105 +449,58 @@ Here is a basic introduction to how the :class:`~markupsafe.Markup` class works:
|
|||
Accessing Request Data
|
||||
----------------------
|
||||
|
||||
For web applications it's crucial to react to the data a client sends to
|
||||
the server. In Flask this information is provided by the global
|
||||
:class:`~flask.request` object. If you have some experience with Python
|
||||
you might be wondering how that object can be global and how Flask
|
||||
manages to still be threadsafe. The answer is context locals:
|
||||
For web applications it's crucial to react to the data a client sends to the
|
||||
server. In Flask this information is provided by the global :data:`.request`
|
||||
object, which is an instance of :class:`.Request`. This object has many
|
||||
attributes and methods to work with the incoming request data, but here is a
|
||||
broad overview. First it needs to be imported.
|
||||
|
||||
|
||||
.. _context-locals:
|
||||
|
||||
Context Locals
|
||||
``````````````
|
||||
|
||||
.. admonition:: Insider Information
|
||||
|
||||
If you want to understand how that works and how you can implement
|
||||
tests with context locals, read this section, otherwise just skip it.
|
||||
|
||||
Certain objects in Flask are global objects, but not of the usual kind.
|
||||
These objects are actually proxies to objects that are local to a specific
|
||||
context. What a mouthful. But that is actually quite easy to understand.
|
||||
|
||||
Imagine the context being the handling thread. A request comes in and the
|
||||
web server decides to spawn a new thread (or something else, the
|
||||
underlying object is capable of dealing with concurrency systems other
|
||||
than threads). When Flask starts its internal request handling it
|
||||
figures out that the current thread is the active context and binds the
|
||||
current application and the WSGI environments to that context (thread).
|
||||
It does that in an intelligent way so that one application can invoke another
|
||||
application without breaking.
|
||||
|
||||
So what does this mean to you? Basically you can completely ignore that
|
||||
this is the case unless you are doing something like unit testing. You
|
||||
will notice that code which depends on a request object will suddenly break
|
||||
because there is no request object. The solution is creating a request
|
||||
object yourself and binding it to the context. The easiest solution for
|
||||
unit testing is to use the :meth:`~flask.Flask.test_request_context`
|
||||
context manager. In combination with the ``with`` statement it will bind a
|
||||
test request so that you can interact with it. Here is an example::
|
||||
.. code-block:: python
|
||||
|
||||
from flask import request
|
||||
|
||||
with app.test_request_context('/hello', method='POST'):
|
||||
# now you can do something with the request until the
|
||||
# end of the with block, such as basic assertions:
|
||||
assert request.path == '/hello'
|
||||
assert request.method == 'POST'
|
||||
If you have some experience with Python you might be wondering how that object
|
||||
can be global when Flask handles multiple requests at a time. The answer is
|
||||
that :data:`.request` is actually a proxy, pointing at whatever request is
|
||||
currently being handled by a given worker, which is managed interanlly by Flask
|
||||
and Python. See :doc:`/appcontext` for much more information.
|
||||
|
||||
The other possibility is passing a whole WSGI environment to the
|
||||
:meth:`~flask.Flask.request_context` method::
|
||||
The current request method is available in the :attr:`~.Request.method`
|
||||
attribute. To access form data (data transmitted in a ``POST`` or ``PUT``
|
||||
request), use the :attr:`~flask.Request.form` attribute, which behaves like a
|
||||
dict.
|
||||
|
||||
with app.request_context(environ):
|
||||
assert request.method == 'POST'
|
||||
.. code-block:: python
|
||||
|
||||
The Request Object
|
||||
``````````````````
|
||||
|
||||
The request object is documented in the API section and we will not cover
|
||||
it here in detail (see :class:`~flask.Request`). Here is a broad overview of
|
||||
some of the most common operations. First of all you have to import it from
|
||||
the ``flask`` module::
|
||||
|
||||
from flask import request
|
||||
|
||||
The current request method is available by using the
|
||||
:attr:`~flask.Request.method` attribute. To access form data (data
|
||||
transmitted in a ``POST`` or ``PUT`` request) you can use the
|
||||
:attr:`~flask.Request.form` attribute. Here is a full example of the two
|
||||
attributes mentioned above::
|
||||
|
||||
@app.route('/login', methods=['POST', 'GET'])
|
||||
@app.route("/login", methods=["GET", "POST"])
|
||||
def login():
|
||||
error = None
|
||||
if request.method == 'POST':
|
||||
if valid_login(request.form['username'],
|
||||
request.form['password']):
|
||||
return log_the_user_in(request.form['username'])
|
||||
|
||||
if request.method == "POST":
|
||||
if valid_login(request.form["username"], request.form["password"]):
|
||||
return store_login(request.form["username"])
|
||||
else:
|
||||
error = 'Invalid username/password'
|
||||
# the code below is executed if the request method
|
||||
# was GET or the credentials were invalid
|
||||
return render_template('login.html', error=error)
|
||||
error = "Invalid username or password"
|
||||
|
||||
What happens if the key does not exist in the ``form`` attribute? In that
|
||||
case a special :exc:`KeyError` is raised. You can catch it like a
|
||||
standard :exc:`KeyError` but if you don't do that, a HTTP 400 Bad Request
|
||||
error page is shown instead. So for many situations you don't have to
|
||||
deal with that problem.
|
||||
# Executed if the request method was GET or the credentials were invalid.
|
||||
return render_template("login.html", error=error)
|
||||
|
||||
To access parameters submitted in the URL (``?key=value``) you can use the
|
||||
:attr:`~flask.Request.args` attribute::
|
||||
If the key does not exist in ``form``, a special :exc:`KeyError` is raised. You
|
||||
can catch it like a normal ``KeyError``, otherwise it will return a HTTP 400
|
||||
Bad Request error page. You can also use the
|
||||
:meth:`~werkzeug.datastructures.MultiDict.get` method to get a default
|
||||
instead of an error.
|
||||
|
||||
To access parameters submitted in the URL (``?key=value``), use the
|
||||
:attr:`~.Request.args` attribute. Key errors behave the same as ``form``,
|
||||
returning a 400 response if not caught.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
searchword = request.args.get('key', '')
|
||||
|
||||
We recommend accessing URL parameters with `get` or by catching the
|
||||
:exc:`KeyError` because users might change the URL and presenting them a 400
|
||||
bad request page in that case is not user friendly.
|
||||
|
||||
For a full list of methods and attributes of the request object, head over
|
||||
to the :class:`~flask.Request` documentation.
|
||||
For a full list of methods and attributes of the request object, see the
|
||||
:class:`~.Request` documentation.
|
||||
|
||||
|
||||
File Uploads
|
||||
|
|
|
|||
|
|
@ -1,243 +1,6 @@
|
|||
.. currentmodule:: flask
|
||||
:orphan:
|
||||
|
||||
The Request Context
|
||||
===================
|
||||
|
||||
The request context keeps track of the request-level data during a
|
||||
request. Rather than passing the request object to each function that
|
||||
runs during a request, the :data:`request` and :data:`session` proxies
|
||||
are accessed instead.
|
||||
|
||||
This is similar to :doc:`/appcontext`, which keeps track of the
|
||||
application-level data independent of a request. A corresponding
|
||||
application context is pushed when a request context is pushed.
|
||||
|
||||
|
||||
Purpose of the Context
|
||||
----------------------
|
||||
|
||||
When the :class:`Flask` application handles a request, it creates a
|
||||
:class:`Request` object based on the environment it received from the
|
||||
WSGI server. Because a *worker* (thread, process, or coroutine depending
|
||||
on the server) handles only one request at a time, the request data can
|
||||
be considered global to that worker during that request. Flask uses the
|
||||
term *context local* for this.
|
||||
|
||||
Flask automatically *pushes* a request context when handling a request.
|
||||
View functions, error handlers, and other functions that run during a
|
||||
request will have access to the :data:`request` proxy, which points to
|
||||
the request object for the current request.
|
||||
|
||||
|
||||
Lifetime of the Context
|
||||
-----------------------
|
||||
|
||||
When a Flask application begins handling a request, it pushes a request
|
||||
context, which also pushes an :doc:`app context </appcontext>`. When the
|
||||
request ends it pops the request context then the application context.
|
||||
|
||||
The context is unique to each thread (or other worker type).
|
||||
:data:`request` cannot be passed to another thread, the other thread has
|
||||
a different context space and will not know about the request the parent
|
||||
thread was pointing to.
|
||||
|
||||
Context locals are implemented using Python's :mod:`contextvars` and
|
||||
Werkzeug's :class:`~werkzeug.local.LocalProxy`. Python manages the
|
||||
lifetime of context vars automatically, and local proxy wraps that
|
||||
low-level interface to make the data easier to work with.
|
||||
|
||||
|
||||
Manually Push a Context
|
||||
-----------------------
|
||||
|
||||
If you try to access :data:`request`, or anything that uses it, outside
|
||||
a request context, you'll get this error message:
|
||||
|
||||
.. code-block:: pytb
|
||||
|
||||
RuntimeError: Working outside of request context.
|
||||
|
||||
This typically means that you attempted to use functionality that
|
||||
needed an active HTTP request. Consult the documentation on testing
|
||||
for information about how to avoid this problem.
|
||||
|
||||
This should typically only happen when testing code that expects an
|
||||
active request. One option is to use the
|
||||
:meth:`test client <Flask.test_client>` to simulate a full request. Or
|
||||
you can use :meth:`~Flask.test_request_context` in a ``with`` block, and
|
||||
everything that runs in the block will have access to :data:`request`,
|
||||
populated with your test data. ::
|
||||
|
||||
def generate_report(year):
|
||||
format = request.args.get("format")
|
||||
...
|
||||
|
||||
with app.test_request_context(
|
||||
"/make_report/2017", query_string={"format": "short"}
|
||||
):
|
||||
generate_report()
|
||||
|
||||
If you see that error somewhere else in your code not related to
|
||||
testing, it most likely indicates that you should move that code into a
|
||||
view function.
|
||||
|
||||
For information on how to use the request context from the interactive
|
||||
Python shell, see :doc:`/shell`.
|
||||
|
||||
|
||||
How the Context Works
|
||||
---------------------
|
||||
|
||||
The :meth:`Flask.wsgi_app` method is called to handle each request. It
|
||||
manages the contexts during the request. Internally, the request and
|
||||
application contexts work like stacks. When contexts are pushed, the
|
||||
proxies that depend on them are available and point at information from
|
||||
the top item.
|
||||
|
||||
When the request starts, a :class:`~ctx.RequestContext` is created and
|
||||
pushed, which creates and pushes an :class:`~ctx.AppContext` first if
|
||||
a context for that application is not already the top context. While
|
||||
these contexts are pushed, the :data:`current_app`, :data:`g`,
|
||||
:data:`request`, and :data:`session` proxies are available to the
|
||||
original thread handling the request.
|
||||
|
||||
Other contexts may be pushed to change the proxies during a request.
|
||||
While this is not a common pattern, it can be used in advanced
|
||||
applications to, for example, do internal redirects or chain different
|
||||
applications together.
|
||||
|
||||
After the request is dispatched and a response is generated and sent,
|
||||
the request context is popped, which then pops the application context.
|
||||
Immediately before they are popped, the :meth:`~Flask.teardown_request`
|
||||
and :meth:`~Flask.teardown_appcontext` functions are executed. These
|
||||
execute even if an unhandled exception occurred during dispatch.
|
||||
|
||||
|
||||
.. _callbacks-and-errors:
|
||||
|
||||
Callbacks and Errors
|
||||
--------------------
|
||||
|
||||
Flask dispatches a request in multiple stages which can affect the
|
||||
request, response, and how errors are handled. The contexts are active
|
||||
during all of these stages.
|
||||
|
||||
A :class:`Blueprint` can add handlers for these events that are specific
|
||||
to the blueprint. The handlers for a blueprint will run if the blueprint
|
||||
owns the route that matches the request.
|
||||
|
||||
#. Before each request, :meth:`~Flask.before_request` functions are
|
||||
called. If one of these functions return a value, the other
|
||||
functions are skipped. The return value is treated as the response
|
||||
and the view function is not called.
|
||||
|
||||
#. If the :meth:`~Flask.before_request` functions did not return a
|
||||
response, the view function for the matched route is called and
|
||||
returns a response.
|
||||
|
||||
#. The return value of the view is converted into an actual response
|
||||
object and passed to the :meth:`~Flask.after_request`
|
||||
functions. Each function returns a modified or new response object.
|
||||
|
||||
#. After the response is returned, the contexts are popped, which calls
|
||||
the :meth:`~Flask.teardown_request` and
|
||||
:meth:`~Flask.teardown_appcontext` functions. These functions are
|
||||
called even if an unhandled exception was raised at any point above.
|
||||
|
||||
If an exception is raised before the teardown functions, Flask tries to
|
||||
match it with an :meth:`~Flask.errorhandler` function to handle the
|
||||
exception and return a response. If no error handler is found, or the
|
||||
handler itself raises an exception, Flask returns a generic
|
||||
``500 Internal Server Error`` response. The teardown functions are still
|
||||
called, and are passed the exception object.
|
||||
|
||||
If debug mode is enabled, unhandled exceptions are not converted to a
|
||||
``500`` response and instead are propagated to the WSGI server. This
|
||||
allows the development server to present the interactive debugger with
|
||||
the traceback.
|
||||
|
||||
|
||||
Teardown Callbacks
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The teardown callbacks are independent of the request dispatch, and are
|
||||
instead called by the contexts when they are popped. The functions are
|
||||
called even if there is an unhandled exception during dispatch, and for
|
||||
manually pushed contexts. This means there is no guarantee that any
|
||||
other parts of the request dispatch have run first. Be sure to write
|
||||
these functions in a way that does not depend on other callbacks and
|
||||
will not fail.
|
||||
|
||||
During testing, it can be useful to defer popping the contexts after the
|
||||
request ends, so that their data can be accessed in the test function.
|
||||
Use the :meth:`~Flask.test_client` as a ``with`` block to preserve the
|
||||
contexts until the ``with`` block exits.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from flask import Flask, request
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route('/')
|
||||
def hello():
|
||||
print('during view')
|
||||
return 'Hello, World!'
|
||||
|
||||
@app.teardown_request
|
||||
def show_teardown(exception):
|
||||
print('after with block')
|
||||
|
||||
with app.test_request_context():
|
||||
print('during with block')
|
||||
|
||||
# teardown functions are called after the context with block exits
|
||||
|
||||
with app.test_client() as client:
|
||||
client.get('/')
|
||||
# the contexts are not popped even though the request ended
|
||||
print(request.path)
|
||||
|
||||
# the contexts are popped and teardown functions are called after
|
||||
# the client with block exits
|
||||
|
||||
Signals
|
||||
~~~~~~~
|
||||
|
||||
The following signals are sent:
|
||||
|
||||
#. :data:`request_started` is sent before the :meth:`~Flask.before_request` functions
|
||||
are called.
|
||||
#. :data:`request_finished` is sent after the :meth:`~Flask.after_request` functions
|
||||
are called.
|
||||
#. :data:`got_request_exception` is sent when an exception begins to be handled, but
|
||||
before an :meth:`~Flask.errorhandler` is looked up or called.
|
||||
#. :data:`request_tearing_down` is sent after the :meth:`~Flask.teardown_request`
|
||||
functions are called.
|
||||
|
||||
|
||||
.. _notes-on-proxies:
|
||||
|
||||
Notes On Proxies
|
||||
----------------
|
||||
|
||||
Some of the objects provided by Flask are proxies to other objects. The
|
||||
proxies are accessed in the same way for each worker thread, but
|
||||
point to the unique object bound to each worker behind the scenes as
|
||||
described on this page.
|
||||
|
||||
Most of the time you don't have to care about that, but there are some
|
||||
exceptions where it is good to know that this object is actually a proxy:
|
||||
|
||||
- The proxy objects cannot fake their type as the actual object types.
|
||||
If you want to perform instance checks, you have to do that on the
|
||||
object being proxied.
|
||||
- The reference to the proxied object is needed in some situations,
|
||||
such as sending :doc:`signals` or passing data to a background
|
||||
thread.
|
||||
|
||||
If you need to access the underlying object that is proxied, use the
|
||||
:meth:`~werkzeug.local.LocalProxy._get_current_object` method::
|
||||
|
||||
app = current_app._get_current_object()
|
||||
my_signal.send(app)
|
||||
Obsolete, see :doc:`/appcontext` instead.
|
||||
|
|
|
|||
|
|
@ -1,56 +1,37 @@
|
|||
Working with the Shell
|
||||
======================
|
||||
|
||||
.. versionadded:: 0.3
|
||||
One of the reasons everybody loves Python is the interactive shell. It allows
|
||||
you to play around with code in real time and immediately get results back.
|
||||
Flask provides the ``flask shell`` CLI command to start an interactive Python
|
||||
shell with some setup done to make working with the Flask app easier.
|
||||
|
||||
One of the reasons everybody loves Python is the interactive shell. It
|
||||
basically allows you to execute Python commands in real time and
|
||||
immediately get results back. Flask itself does not come with an
|
||||
interactive shell, because it does not require any specific setup upfront,
|
||||
just import your application and start playing around.
|
||||
.. code-block:: text
|
||||
|
||||
There are however some handy helpers to make playing around in the shell a
|
||||
more pleasant experience. The main issue with interactive console
|
||||
sessions is that you're not triggering a request like a browser does which
|
||||
means that :data:`~flask.g`, :data:`~flask.request` and others are not
|
||||
available. But the code you want to test might depend on them, so what
|
||||
can you do?
|
||||
|
||||
This is where some helper functions come in handy. Keep in mind however
|
||||
that these functions are not only there for interactive shell usage, but
|
||||
also for unit testing and other situations that require a faked request
|
||||
context.
|
||||
|
||||
Generally it's recommended that you read :doc:`reqcontext` first.
|
||||
|
||||
Command Line Interface
|
||||
----------------------
|
||||
|
||||
Starting with Flask 0.11 the recommended way to work with the shell is the
|
||||
``flask shell`` command which does a lot of this automatically for you.
|
||||
For instance the shell is automatically initialized with a loaded
|
||||
application context.
|
||||
|
||||
For more information see :doc:`/cli`.
|
||||
$ flask shell
|
||||
|
||||
Creating a Request Context
|
||||
--------------------------
|
||||
|
||||
``flask shell`` pushes an app context automatically, so :data:`.current_app` and
|
||||
:data:`.g` are already available. However, there is no HTTP request being
|
||||
handled in the shell, so :data:`.request` and :data:`.session` are not yet
|
||||
available.
|
||||
|
||||
The easiest way to create a proper request context from the shell is by
|
||||
using the :attr:`~flask.Flask.test_request_context` method which creates
|
||||
us a :class:`~flask.ctx.RequestContext`:
|
||||
|
||||
>>> ctx = app.test_request_context()
|
||||
|
||||
Normally you would use the ``with`` statement to make this request object
|
||||
active, but in the shell it's easier to use the
|
||||
:meth:`~flask.ctx.RequestContext.push` and
|
||||
:meth:`~flask.ctx.RequestContext.pop` methods by hand:
|
||||
Normally you would use the ``with`` statement to make this context active, but
|
||||
in the shell it's easier to call :meth:`~.RequestContext.push` and
|
||||
:meth:`~.RequestContext.pop` manually:
|
||||
|
||||
>>> ctx.push()
|
||||
|
||||
From that point onwards you can work with the request object until you
|
||||
call `pop`:
|
||||
From that point onwards you can work with the request object until you call
|
||||
``pop``:
|
||||
|
||||
>>> ctx.pop()
|
||||
|
||||
|
|
|
|||
|
|
@ -144,11 +144,10 @@ function, you can pass ``current_app._get_current_object()`` as sender.
|
|||
Signals and Flask's Request Context
|
||||
-----------------------------------
|
||||
|
||||
Signals fully support :doc:`reqcontext` when receiving signals.
|
||||
Context-local variables are consistently available between
|
||||
:data:`~flask.request_started` and :data:`~flask.request_finished`, so you can
|
||||
rely on :class:`flask.g` and others as needed. Note the limitations described
|
||||
in :ref:`signals-sending` and the :data:`~flask.request_tearing_down` signal.
|
||||
Context-local proxies are available between :data:`~flask.request_started` and
|
||||
:data:`~flask.request_finished`, so you can rely on :class:`flask.g` and others
|
||||
as needed. Note the limitations described in :ref:`signals-sending` and the
|
||||
:data:`~flask.request_tearing_down` signal.
|
||||
|
||||
|
||||
Decorator Based Signal Subscriptions
|
||||
|
|
|
|||
|
|
@ -275,11 +275,10 @@ command from the command line.
|
|||
Tests that depend on an Active Context
|
||||
--------------------------------------
|
||||
|
||||
You may have functions that are called from views or commands, that
|
||||
expect an active :doc:`application context </appcontext>` or
|
||||
:doc:`request context </reqcontext>` because they access ``request``,
|
||||
``session``, or ``current_app``. Rather than testing them by making a
|
||||
request or invoking the command, you can create and activate a context
|
||||
You may have functions that are called from views or commands, that expect an
|
||||
active :doc:`app context </appcontext>` because they access :data:`.request`,
|
||||
:data:`.session`, :data:`.g`, or :data:`.current_app`. Rather than testing them by
|
||||
making a request or invoking the command, you can create and activate a context
|
||||
directly.
|
||||
|
||||
Use ``with app.app_context()`` to push an application context. For
|
||||
|
|
|
|||
|
|
@ -305,7 +305,7 @@ The pattern ``{{ request.form['title'] or post['title'] }}`` is used to
|
|||
choose what data appears in the form. When the form hasn't been
|
||||
submitted, the original ``post`` data appears, but if invalid form data
|
||||
was posted you want to display that so the user can fix the error, so
|
||||
``request.form`` is used instead. :data:`request` is another variable
|
||||
``request.form`` is used instead. :data:`.request` is another variable
|
||||
that's automatically available in templates.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -60,17 +60,17 @@ response is sent.
|
|||
if db is not None:
|
||||
db.close()
|
||||
|
||||
:data:`g` is a special object that is unique for each request. It is
|
||||
:data:`.g` is a special object that is unique for each request. It is
|
||||
used to store data that might be accessed by multiple functions during
|
||||
the request. The connection is stored and reused instead of creating a
|
||||
new connection if ``get_db`` is called a second time in the same
|
||||
request.
|
||||
|
||||
:data:`current_app` is another special object that points to the Flask
|
||||
:data:`.current_app` is another special object that points to the Flask
|
||||
application handling the request. Since you used an application factory,
|
||||
there is no application object when writing the rest of your code.
|
||||
``get_db`` will be called when the application has been created and is
|
||||
handling a request, so :data:`current_app` can be used.
|
||||
handling a request, so :data:`.current_app` can be used.
|
||||
|
||||
:func:`sqlite3.connect` establishes a connection to the file pointed at
|
||||
by the ``DATABASE`` configuration key. This file doesn't have to exist
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ specific sections.
|
|||
{% block content %}{% endblock %}
|
||||
</section>
|
||||
|
||||
:data:`g` is automatically available in templates. Based on if
|
||||
:data:`.g` is automatically available in templates. Based on if
|
||||
``g.user`` is set (from ``load_logged_in_user``), either the username
|
||||
and a log out link are displayed, or links to register and log in
|
||||
are displayed. :func:`url_for` is also automatically available, and is
|
||||
|
|
|
|||
|
|
@ -311,7 +311,7 @@ input and error messages without writing the same code three times.
|
|||
|
||||
The tests for the ``login`` view are very similar to those for
|
||||
``register``. Rather than testing the data in the database,
|
||||
:data:`session` should have ``user_id`` set after logging in.
|
||||
:data:`.session` should have ``user_id`` set after logging in.
|
||||
|
||||
.. code-block:: python
|
||||
:caption: ``tests/test_auth.py``
|
||||
|
|
@ -336,10 +336,10 @@ The tests for the ``login`` view are very similar to those for
|
|||
assert message in response.data
|
||||
|
||||
Using ``client`` in a ``with`` block allows accessing context variables
|
||||
such as :data:`session` after the response is returned. Normally,
|
||||
such as :data:`.session` after the response is returned. Normally,
|
||||
accessing ``session`` outside of a request would raise an error.
|
||||
|
||||
Testing ``logout`` is the opposite of ``login``. :data:`session` should
|
||||
Testing ``logout`` is the opposite of ``login``. :data:`.session` should
|
||||
not contain ``user_id`` after logging out.
|
||||
|
||||
.. code-block:: python
|
||||
|
|
|
|||
|
|
@ -208,13 +208,13 @@ There are a few differences from the ``register`` view:
|
|||
password in the same way as the stored hash and securely compares
|
||||
them. If they match, the password is valid.
|
||||
|
||||
#. :data:`session` is a :class:`dict` that stores data across requests.
|
||||
#. :data:`.session` is a :class:`dict` that stores data across requests.
|
||||
When validation succeeds, the user's ``id`` is stored in a new
|
||||
session. The data is stored in a *cookie* that is sent to the
|
||||
browser, and the browser then sends it back with subsequent requests.
|
||||
Flask securely *signs* the data so that it can't be tampered with.
|
||||
|
||||
Now that the user's ``id`` is stored in the :data:`session`, it will be
|
||||
Now that the user's ``id`` is stored in the :data:`.session`, it will be
|
||||
available on subsequent requests. At the beginning of each request, if
|
||||
a user is logged in their information should be loaded and made
|
||||
available to other views.
|
||||
|
|
@ -236,7 +236,7 @@ available to other views.
|
|||
:meth:`bp.before_app_request() <Blueprint.before_app_request>` registers
|
||||
a function that runs before the view function, no matter what URL is
|
||||
requested. ``load_logged_in_user`` checks if a user id is stored in the
|
||||
:data:`session` and gets that user's data from the database, storing it
|
||||
:data:`.session` and gets that user's data from the database, storing it
|
||||
on :data:`g.user <g>`, which lasts for the length of the request. If
|
||||
there is no user id, or if the id doesn't exist, ``g.user`` will be
|
||||
``None``.
|
||||
|
|
@ -245,7 +245,7 @@ there is no user id, or if the id doesn't exist, ``g.user`` will be
|
|||
Logout
|
||||
------
|
||||
|
||||
To log out, you need to remove the user id from the :data:`session`.
|
||||
To log out, you need to remove the user id from the :data:`.session`.
|
||||
Then ``load_logged_in_user`` won't load a user on subsequent requests.
|
||||
|
||||
.. code-block:: python
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue