forked from orbit-oss/flask
Merge pull request #2685 from davidism/app-context-docs
rework context docs
This commit is contained in:
commit
16d83d6bb4
7 changed files with 534 additions and 367 deletions
93
docs/api.rst
93
docs/api.rst
|
|
@ -211,29 +211,22 @@ thing, like it does for :class:`request` and :class:`session`.
|
||||||
|
|
||||||
.. data:: g
|
.. data:: g
|
||||||
|
|
||||||
Just store on this whatever you want. For example a database
|
A namespace object that can store data during an
|
||||||
connection or the user that is currently logged in.
|
:doc:`application context </appcontext>`. This is an instance of
|
||||||
|
:attr:`Flask.app_ctx_globals_class`, which defaults to
|
||||||
|
:class:`ctx._AppCtxGlobals`.
|
||||||
|
|
||||||
Starting with Flask 0.10 this is stored on the application context and
|
This is a good place to store resources during a request. During
|
||||||
no longer on the request context which means it becomes available if
|
testing, you can use the :ref:`faking-resources` pattern to
|
||||||
only the application context is bound and not yet a request. This
|
pre-configure such resources.
|
||||||
is especially useful when combined with the :ref:`faking-resources`
|
|
||||||
pattern for testing.
|
|
||||||
|
|
||||||
Additionally as of 0.10 you can use the :meth:`get` method to
|
This is a proxy. See :ref:`notes-on-proxies` for more information.
|
||||||
get an attribute or ``None`` (or the second argument) if it's not set.
|
|
||||||
These two usages are now equivalent::
|
|
||||||
|
|
||||||
user = getattr(flask.g, 'user', None)
|
.. versionchanged:: 0.10
|
||||||
user = flask.g.get('user', None)
|
Bound to the application context instead of the request context.
|
||||||
|
|
||||||
It's now also possible to use the ``in`` operator on it to see if an
|
.. autoclass:: flask.ctx._AppCtxGlobals
|
||||||
attribute is defined and it yields all keys on iteration.
|
:members:
|
||||||
|
|
||||||
As of 0.11 you can use :meth:`pop` and :meth:`setdefault` in the same
|
|
||||||
way you would use them on a dictionary.
|
|
||||||
|
|
||||||
This is a proxy. See :ref:`notes-on-proxies` for more information.
|
|
||||||
|
|
||||||
|
|
||||||
Useful Functions and Classes
|
Useful Functions and Classes
|
||||||
|
|
@ -241,13 +234,17 @@ Useful Functions and Classes
|
||||||
|
|
||||||
.. data:: current_app
|
.. data:: current_app
|
||||||
|
|
||||||
Points to the application handling the request. This is useful for
|
A proxy to the application handling the current request. This is
|
||||||
extensions that want to support multiple applications running side
|
useful to access the application without needing to import it, or if
|
||||||
by side. This is powered by the application context and not by the
|
it can't be imported, such as when using the application factory
|
||||||
request context, so you can change the value of this proxy by
|
pattern or in blueprints and extensions.
|
||||||
using the :meth:`~flask.Flask.app_context` method.
|
|
||||||
|
|
||||||
This is a proxy. See :ref:`notes-on-proxies` for more information.
|
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 a proxy. See :ref:`notes-on-proxies` for more information.
|
||||||
|
|
||||||
.. autofunction:: has_request_context
|
.. autofunction:: has_request_context
|
||||||
|
|
||||||
|
|
@ -384,50 +381,54 @@ Useful Internals
|
||||||
|
|
||||||
.. data:: _request_ctx_stack
|
.. data:: _request_ctx_stack
|
||||||
|
|
||||||
The internal :class:`~werkzeug.local.LocalStack` that is used to implement
|
The internal :class:`~werkzeug.local.LocalStack` that holds
|
||||||
all the context local objects used in Flask. This is a documented
|
:class:`~flask.ctx.RequestContext` instances. Typically, the
|
||||||
instance and can be used by extensions and application code but the
|
:data:`request` and :data:`session` proxies should be accessed
|
||||||
use is discouraged in general.
|
instead of the stack. It may be useful to access the stack in
|
||||||
|
extension code.
|
||||||
|
|
||||||
The following attributes are always present on each layer of the
|
The following attributes are always present on each layer of the
|
||||||
stack:
|
stack:
|
||||||
|
|
||||||
`app`
|
`app`
|
||||||
the active Flask application.
|
the active Flask application.
|
||||||
|
|
||||||
`url_adapter`
|
`url_adapter`
|
||||||
the URL adapter that was used to match the request.
|
the URL adapter that was used to match the request.
|
||||||
|
|
||||||
`request`
|
`request`
|
||||||
the current request object.
|
the current request object.
|
||||||
|
|
||||||
`session`
|
`session`
|
||||||
the active session object.
|
the active session object.
|
||||||
|
|
||||||
`g`
|
`g`
|
||||||
an object with all the attributes of the :data:`flask.g` object.
|
an object with all the attributes of the :data:`flask.g` object.
|
||||||
|
|
||||||
`flashes`
|
`flashes`
|
||||||
an internal cache for the flashed messages.
|
an internal cache for the flashed messages.
|
||||||
|
|
||||||
Example usage::
|
Example usage::
|
||||||
|
|
||||||
from flask import _request_ctx_stack
|
from flask import _request_ctx_stack
|
||||||
|
|
||||||
def get_session():
|
def get_session():
|
||||||
ctx = _request_ctx_stack.top
|
ctx = _request_ctx_stack.top
|
||||||
if ctx is not None:
|
if ctx is not None:
|
||||||
return ctx.session
|
return ctx.session
|
||||||
|
|
||||||
.. autoclass:: flask.ctx.AppContext
|
.. autoclass:: flask.ctx.AppContext
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
.. data:: _app_ctx_stack
|
.. data:: _app_ctx_stack
|
||||||
|
|
||||||
Works similar to the request context but only binds the application.
|
The internal :class:`~werkzeug.local.LocalStack` that holds
|
||||||
This is mainly there for extensions to store data.
|
:class:`~flask.ctx.AppContext` instances. Typically, the
|
||||||
|
:data:`current_app` and :data:`g` proxies should be accessed instead
|
||||||
|
of the stack. Extensions can access the contexts on the stack as a
|
||||||
|
namespace to store data.
|
||||||
|
|
||||||
.. versionadded:: 0.9
|
.. versionadded:: 0.9
|
||||||
|
|
||||||
.. autoclass:: flask.blueprints.BlueprintSetupState
|
.. autoclass:: flask.blueprints.BlueprintSetupState
|
||||||
:members:
|
:members:
|
||||||
|
|
|
||||||
|
|
@ -1,144 +1,159 @@
|
||||||
|
.. currentmodule:: flask
|
||||||
|
|
||||||
.. _app-context:
|
.. _app-context:
|
||||||
|
|
||||||
The Application Context
|
The Application Context
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
.. versionadded:: 0.9
|
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.
|
||||||
|
|
||||||
One of the design ideas behind Flask is that there are at least two
|
This is similar to the :doc:`/reqcontext`, which keeps track of
|
||||||
different “states” in which code is executed:
|
request-level data during a request. A corresponding application context
|
||||||
|
is pushed when a request context is pushed.
|
||||||
|
|
||||||
1. The application setup state, in which the application implicitly is
|
Purpose of the Context
|
||||||
on the module level.
|
----------------------
|
||||||
|
|
||||||
This state starts when the :class:`Flask` object is instantiated, and
|
The :class:`Flask` application object has attributes, such as
|
||||||
it implicitly ends when the first request comes in. While the
|
:attr:`~Flask.config`, that are useful to access within views and
|
||||||
application is in this state, a few assumptions are true:
|
: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 programmer can modify the application object safely.
|
Flask solves this issue with the *application context*. Rather than
|
||||||
- no request handling happened so far
|
referring to an ``app`` directly, you use the the :data:`current_app`
|
||||||
- you have to have a reference to the application object in order to
|
proxy, which points to the application handling the current activity.
|
||||||
modify it, there is no magic proxy that can give you a reference to
|
|
||||||
the application object you're currently creating or modifying.
|
|
||||||
|
|
||||||
2. In contrast, in the request handling state, a couple of other rules
|
Flask automatically *pushes* an application context when handling a
|
||||||
exist:
|
request. View functions, error handlers, and other functions that run
|
||||||
|
during a request will have access to :data:`current_app`.
|
||||||
|
|
||||||
- while a request is active, the context local objects
|
Flask will also automatically push an app context when running CLI
|
||||||
(:data:`flask.request` and others) point to the current request.
|
commands registered with :attr:`Flask.cli` using ``@app.cli.command()``.
|
||||||
- any code can get hold of these objects at any time.
|
|
||||||
|
|
||||||
3. There is also a third state somewhere in between 'module-level' and
|
|
||||||
'request-handling':
|
|
||||||
|
|
||||||
Sometimes you are dealing with an application in a way that is similar to
|
Lifetime of the Context
|
||||||
how you interact with applications during request handling, but without
|
-----------------------
|
||||||
there being an active request. Consider, for instance, that you're
|
|
||||||
sitting in an interactive Python shell and interacting with the
|
|
||||||
application, or a command line application.
|
|
||||||
|
|
||||||
The application context is what powers the :data:`~flask.current_app`
|
The application context is created and destroyed as necessary. When a
|
||||||
context local.
|
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.
|
||||||
|
|
||||||
Purpose of the Application Context
|
See :doc:`/reqcontext` for more information about how the contexts work
|
||||||
----------------------------------
|
and the full lifecycle of a request.
|
||||||
|
|
||||||
The main reason for the application's context existence is that in the
|
|
||||||
past a bunch of functionality was attached to the request context for lack
|
|
||||||
of a better solution. Since one of the pillars of Flask's design is that
|
|
||||||
you can have more than one application in the same Python process.
|
|
||||||
|
|
||||||
So how does the code find the “right” application? In the past we
|
Manually Push a Context
|
||||||
recommended passing applications around explicitly, but that caused issues
|
-----------------------
|
||||||
with libraries that were not designed with that in mind.
|
|
||||||
|
|
||||||
A common workaround for that problem was to use the
|
If you try to access :data:`current_app`, or anything that uses it,
|
||||||
:data:`~flask.current_app` proxy later on, which was bound to the current
|
outside an application context, you'll get this error message:
|
||||||
request's application reference. Since creating such a request context is
|
|
||||||
an unnecessarily expensive operation in case there is no request around,
|
|
||||||
the application context was introduced.
|
|
||||||
|
|
||||||
Creating an Application Context
|
.. code-block:: pytb
|
||||||
-------------------------------
|
|
||||||
|
|
||||||
There are two ways to make an application context. The first one is
|
|
||||||
implicit: whenever a request context is pushed, an application context
|
|
||||||
will be created alongside if this is necessary. As a result, you can
|
|
||||||
ignore the existence of the application context unless you need it.
|
|
||||||
|
|
||||||
The second way is the explicit way using the
|
|
||||||
:meth:`~flask.Flask.app_context` method::
|
|
||||||
|
|
||||||
from flask import Flask, current_app
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
|
||||||
with app.app_context():
|
|
||||||
# within this block, current_app points to app.
|
|
||||||
print current_app.name
|
|
||||||
|
|
||||||
The application context is also used by the :func:`~flask.url_for`
|
|
||||||
function in case a ``SERVER_NAME`` was configured. This allows you to
|
|
||||||
generate URLs even in the absence of a request.
|
|
||||||
|
|
||||||
If no request context has been pushed and an application context has
|
|
||||||
not been explicitly set, a ``RuntimeError`` will be raised. ::
|
|
||||||
|
|
||||||
RuntimeError: Working outside of application context.
|
RuntimeError: Working outside of application context.
|
||||||
|
|
||||||
Locality of the 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().
|
||||||
|
|
||||||
The application context is created and destroyed as necessary. It never
|
If you see that error while configuring your application, such as when
|
||||||
moves between threads and it will not be shared between requests. As such
|
initializing an extension, you can push a context manually since you
|
||||||
it is the perfect place to store database connection information and other
|
have direct access to the ``app``. Use :meth:`~Flask.app_context` in a
|
||||||
things. The internal stack object is called :data:`flask._app_ctx_stack`.
|
``with`` block, and everything that runs in the block will have access
|
||||||
Extensions are free to store additional information on the topmost level,
|
to :data:`current_app`. ::
|
||||||
assuming they pick a sufficiently unique name and should put their
|
|
||||||
information there, instead of on the :data:`flask.g` object which is reserved
|
|
||||||
for user code.
|
|
||||||
|
|
||||||
For more information about that, see :ref:`extension-dev`.
|
def create_app():
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
Context Usage
|
with app.app_context():
|
||||||
-------------
|
init_db()
|
||||||
|
|
||||||
The context is typically used to cache resources that need to be created
|
return app
|
||||||
on a per-request or usage case. For instance, database connections are
|
|
||||||
destined to go there. When storing things on the application context
|
|
||||||
unique names should be chosen as this is a place that is shared between
|
|
||||||
Flask applications and extensions.
|
|
||||||
|
|
||||||
The most common usage is to split resource management into two parts:
|
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.
|
||||||
|
|
||||||
1. an implicit resource caching on the context.
|
|
||||||
2. a context teardown based resource deallocation.
|
|
||||||
|
|
||||||
Generally there would be a ``get_X()`` function that creates resource
|
Storing Data
|
||||||
``X`` if it does not exist yet and otherwise returns the same resource,
|
------------
|
||||||
and a ``teardown_X()`` function that is registered as teardown handler.
|
|
||||||
|
|
||||||
This is an example that connects to a database::
|
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::
|
||||||
|
|
||||||
import sqlite3
|
|
||||||
from flask import g
|
from flask import g
|
||||||
|
|
||||||
def get_db():
|
def get_db():
|
||||||
db = getattr(g, '_database', None)
|
if 'db' not in g:
|
||||||
if db is None:
|
g.db = connect_to_database()
|
||||||
db = g._database = connect_to_database()
|
|
||||||
return db
|
return g.db
|
||||||
|
|
||||||
@app.teardown_appcontext
|
@app.teardown_appcontext
|
||||||
def teardown_db(exception):
|
def teardown_db():
|
||||||
db = getattr(g, '_database', None)
|
db = g.pop('db', None)
|
||||||
|
|
||||||
if db is not None:
|
if db is not None:
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
The first time ``get_db()`` is called the connection will be established.
|
During a request, every call to ``get_db()`` will return the same
|
||||||
To make this implicit a :class:`~werkzeug.local.LocalProxy` can be used::
|
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
|
from werkzeug.local import LocalProxy
|
||||||
db = LocalProxy(get_db)
|
db = LocalProxy(get_db)
|
||||||
|
|
||||||
That way a user can directly access ``db`` which internally calls
|
Accessing ``db`` will call ``get_db`` internally, in the same way that
|
||||||
``get_db()``.
|
: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`.
|
||||||
|
|
|
||||||
|
|
@ -1,224 +1,267 @@
|
||||||
|
.. currentmodule:: flask
|
||||||
|
|
||||||
.. _request-context:
|
.. _request-context:
|
||||||
|
|
||||||
The Request Context
|
The Request Context
|
||||||
===================
|
===================
|
||||||
|
|
||||||
This document describes the behavior in Flask 0.7 which is mostly in line
|
The request context keeps track of the request-level data during a
|
||||||
with the old behavior but has some small, subtle differences.
|
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.
|
||||||
|
|
||||||
It is recommended that you read the :ref:`app-context` chapter first.
|
This is similar to the :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.
|
||||||
|
|
||||||
Diving into Context Locals
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
Say you have a utility function that returns the URL the user should be
|
Purpose of the Context
|
||||||
redirected to. Imagine it would always redirect to the URL's ``next``
|
----------------------
|
||||||
parameter or the HTTP referrer or the index page::
|
|
||||||
|
|
||||||
from flask import request, url_for
|
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.
|
||||||
|
|
||||||
def redirect_url():
|
Flask automatically *pushes* a request context when handling a request.
|
||||||
return request.args.get('next') or \
|
View functions, error handlers, and other functions that run during a
|
||||||
request.referrer or \
|
request will have access to the :data:`request` proxy, which points to
|
||||||
url_for('index')
|
the request object for the current request.
|
||||||
|
|
||||||
As you can see, it accesses the request object. If you try to run this
|
|
||||||
from a plain Python shell, this is the exception you will see:
|
|
||||||
|
|
||||||
>>> redirect_url()
|
Lifetime of the Context
|
||||||
Traceback (most recent call last):
|
-----------------------
|
||||||
File "<stdin>", line 1, in <module>
|
|
||||||
AttributeError: 'NoneType' object has no attribute 'request'
|
|
||||||
|
|
||||||
That makes a lot of sense because we currently do not have a request we
|
When a Flask application begins handling a request, it pushes a request
|
||||||
could access. So we have to make a request and bind it to the current
|
context, which also pushes an :doc:`/appcontext`. When the request ends
|
||||||
context. The :attr:`~flask.Flask.test_request_context` method can create
|
it pops the request context then the application context.
|
||||||
us a :class:`~flask.ctx.RequestContext`:
|
|
||||||
|
|
||||||
>>> ctx = app.test_request_context('/?next=http://example.com/')
|
The context is unique to each thread (or other worker type).
|
||||||
|
:data:`request` cannot be passed to another thread, the other thread
|
||||||
|
will have a different context stack and will not know about the request
|
||||||
|
the parent thread was pointing to.
|
||||||
|
|
||||||
This context can be used in two ways. Either with the ``with`` statement
|
Context locals are implemented in Werkzeug. See :doc:`werkzeug:local`
|
||||||
or by calling the :meth:`~flask.ctx.RequestContext.push` and
|
for more information on how this works internally.
|
||||||
:meth:`~flask.ctx.RequestContext.pop` methods:
|
|
||||||
|
|
||||||
>>> ctx.push()
|
|
||||||
|
|
||||||
From that point onwards you can work with the request object:
|
Manually Push a Context
|
||||||
|
-----------------------
|
||||||
|
|
||||||
>>> redirect_url()
|
If you try to access :data:`request`, or anything that uses it, outside
|
||||||
u'http://example.com/'
|
a request context, you'll get this error message:
|
||||||
|
|
||||||
Until you call `pop`:
|
.. code-block:: pytb
|
||||||
|
|
||||||
>>> ctx.pop()
|
RuntimeError: Working outside of request context.
|
||||||
|
|
||||||
Because the request context is internally maintained as a stack you can
|
This typically means that you attempted to use functionality that
|
||||||
push and pop multiple times. This is very handy to implement things like
|
needed an active HTTP request. Consult the documentation on testing
|
||||||
internal redirects.
|
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', data={'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`.
|
||||||
|
|
||||||
For more information of how to utilize the request context from the
|
|
||||||
interactive Python shell, head over to the :ref:`shell` chapter.
|
|
||||||
|
|
||||||
How the Context Works
|
How the Context Works
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
If you look into how the Flask WSGI application internally works, you will
|
The :meth:`Flask.wsgi_app` method is called to handle each request. It
|
||||||
find a piece of code that looks very much like this::
|
manages the contexts during the request. Internally, the request and
|
||||||
|
application contexts work as stacks, :data:`_request_ctx_stack` and
|
||||||
|
:data:`_app_ctx_stack`. When contexts are pushed onto the stack, the
|
||||||
|
proxies that depend on them are available and point at information from
|
||||||
|
the top context on the stack.
|
||||||
|
|
||||||
def wsgi_app(self, environ):
|
When the request starts, a :class:`~ctx.RequestContext` is created and
|
||||||
with self.request_context(environ):
|
pushed, which creates and pushes an :class:`~ctx.AppContext` first if
|
||||||
try:
|
a context for that application is not already the top context. While
|
||||||
response = self.full_dispatch_request()
|
these contexts are pushed, the :data:`current_app`, :data:`g`,
|
||||||
except Exception as e:
|
:data:`request`, and :data:`session` proxies are available to the
|
||||||
response = self.make_response(self.handle_exception(e))
|
original thread handling the request.
|
||||||
return response(environ, start_response)
|
|
||||||
|
|
||||||
The method :meth:`~Flask.request_context` returns a new
|
Because the contexts are stacks, other contexts may be pushed to change
|
||||||
:class:`~flask.ctx.RequestContext` object and uses it in combination with
|
the proxies during a request. While this is not a common pattern, it
|
||||||
the ``with`` statement to bind the context. Everything that is called from
|
can be used in advanced applications to, for example, do internal
|
||||||
the same thread from this point onwards until the end of the ``with``
|
redirects or chain different applications together.
|
||||||
statement will have access to the request globals (:data:`flask.request`
|
|
||||||
and others).
|
|
||||||
|
|
||||||
The request context internally works like a stack: The topmost level on
|
After the request is dispatched and a response is generated and sent,
|
||||||
the stack is the current active request.
|
the request context is popped, which then pops the application context.
|
||||||
:meth:`~flask.ctx.RequestContext.push` adds the context to the stack on
|
Immediately before they are popped, the :meth:`~Flask.teardown_request`
|
||||||
the very top, :meth:`~flask.ctx.RequestContext.pop` removes it from the
|
and :meth:`~Flask.teardown_appcontext` functions are are executed. These
|
||||||
stack again. On popping the application's
|
execute even if an unhandled exception occurred during dispatch.
|
||||||
:func:`~flask.Flask.teardown_request` functions are also executed.
|
|
||||||
|
|
||||||
Another thing of note is that the request context will automatically also
|
|
||||||
create an :ref:`application context <app-context>` when it's pushed and
|
|
||||||
there is no application context for that application so far.
|
|
||||||
|
|
||||||
.. _callbacks-and-errors:
|
.. _callbacks-and-errors:
|
||||||
|
|
||||||
Callbacks and Errors
|
Callbacks and Errors
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
What happens if an error occurs in Flask during request processing? This
|
Flask dispatches a request in multiple stages which can affect the
|
||||||
particular behavior changed in 0.7 because we wanted to make it easier to
|
request, response, and how errors are handled. The contexts are active
|
||||||
understand what is actually happening. The new behavior is quite simple:
|
during all of these stages.
|
||||||
|
|
||||||
1. Before each request, :meth:`~flask.Flask.before_request` functions are
|
A :class:`Blueprint` can add handlers for these events that are specific
|
||||||
executed. If one of these functions return a response, the other
|
to the blueprint. The handlers for a blueprint will run if the blueprint
|
||||||
functions are no longer called. In any case however the return value
|
owns the route that matches the request.
|
||||||
is treated as a replacement for the view's return value.
|
|
||||||
|
|
||||||
2. If the :meth:`~flask.Flask.before_request` functions did not return a
|
#. Before each request, :meth:`~Flask.before_request` functions are
|
||||||
response, the regular request handling kicks in and the view function
|
called. If one of these functions return a value, the other
|
||||||
that was matched has the chance to return a response.
|
functions are skipped. The return value is treated as the response
|
||||||
|
and the view function is not called.
|
||||||
|
|
||||||
3. The return value of the view is then converted into an actual response
|
#. If the :meth:`~Flask.before_request` functions did not return a
|
||||||
object and handed over to the :meth:`~flask.Flask.after_request`
|
response, the view function for the matched route is called and
|
||||||
functions which have the chance to replace it or modify it in place.
|
returns a response.
|
||||||
|
|
||||||
4. At the end of the request the :meth:`~flask.Flask.teardown_request`
|
#. The return value of the view is converted into an actual response
|
||||||
functions are executed. This always happens, even in case of an
|
object and passed to the :meth:`~Flask.after_request`
|
||||||
unhandled exception down the road or if a before-request handler was
|
functions. Each function returns a modified or new response object.
|
||||||
not executed yet or at all (for example in test environments sometimes
|
|
||||||
you might want to not execute before-request callbacks).
|
|
||||||
|
|
||||||
Now what happens on errors? If you are not in debug mode and an exception is not
|
#. After the response is returned, the contexts are popped, which calls
|
||||||
caught, the 500 internal server handler is called. In debug mode
|
the :meth:`~Flask.teardown_request` and
|
||||||
however the exception is not further processed and bubbles up to the WSGI
|
:meth:`~Flask.teardown_appcontext` functions. These functions are
|
||||||
server. That way things like the interactive debugger can provide helpful
|
called even if an unhandled exception was raised at any point above.
|
||||||
debug information.
|
|
||||||
|
|
||||||
An important change in 0.7 is that the internal server error is now no
|
If an exception is raised before the teardown functions, Flask tries to
|
||||||
longer post processed by the after request callbacks and after request
|
match it with an :meth:`~Flask.errorhandler` function to handle the
|
||||||
callbacks are no longer guaranteed to be executed. This way the internal
|
exception and return a response. If no error handler is found, or the
|
||||||
dispatching code looks cleaner and is easier to customize and understand.
|
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.
|
||||||
|
|
||||||
The new teardown functions are supposed to be used as a replacement for
|
|
||||||
things that absolutely need to happen at the end of request.
|
|
||||||
|
|
||||||
Teardown Callbacks
|
Teardown Callbacks
|
||||||
------------------
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
The teardown callbacks are special callbacks in that they are executed at
|
The teardown callbacks are independent of the request dispatch, and are
|
||||||
a different point. Strictly speaking they are independent of the actual
|
instead called by the contexts when they are popped. The functions are
|
||||||
request handling as they are bound to the lifecycle of the
|
called even if there is an unhandled exception during dispatch, and for
|
||||||
:class:`~flask.ctx.RequestContext` object. When the request context is
|
manually pushed contexts. This means there is no guarantee that any
|
||||||
popped, the :meth:`~flask.Flask.teardown_request` functions are called.
|
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.
|
||||||
|
|
||||||
This is important to know if the life of the request context is prolonged
|
During testing, it can be useful to defer popping the contexts after the
|
||||||
by using the test client in a with statement or when using the request
|
request ends, so that their data can be accessed in the test function.
|
||||||
context from the command line::
|
Using the :meth:`~Flask.test_client` as a ``with`` block to preserve the
|
||||||
|
contexts until the with block exits.
|
||||||
|
|
||||||
with app.test_client() as client:
|
.. code-block:: python
|
||||||
resp = client.get('/foo')
|
|
||||||
# the teardown functions are still not called at that point
|
|
||||||
# even though the response ended and you have the response
|
|
||||||
# object in your hand
|
|
||||||
|
|
||||||
# only when the code reaches this point the teardown functions
|
from flask import Flask, request
|
||||||
# are called. Alternatively the same thing happens if another
|
|
||||||
# request was triggered from the test client
|
|
||||||
|
|
||||||
It's easy to see the behavior from the command line:
|
app = Flask(__name__)
|
||||||
|
|
||||||
>>> app = Flask(__name__)
|
@app.route('/')
|
||||||
>>> @app.teardown_request
|
def hello():
|
||||||
... def teardown_request(exception=None):
|
print('during view')
|
||||||
... print 'this runs after request'
|
return 'Hello, World!'
|
||||||
...
|
|
||||||
>>> ctx = app.test_request_context()
|
@app.teardown_request
|
||||||
>>> ctx.push()
|
def show_teardown(exception):
|
||||||
>>> ctx.pop()
|
print('after with block')
|
||||||
this runs after request
|
|
||||||
>>>
|
with app.test_request_context():
|
||||||
|
print('during with block')
|
||||||
|
|
||||||
|
# teardown functions are called after the context with block exits
|
||||||
|
|
||||||
|
with app.test_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 exists
|
||||||
|
|
||||||
|
|
||||||
|
Signals
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
If :data:`~signals.signals_available` is true, 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.
|
||||||
|
|
||||||
|
|
||||||
|
Context Preservation on Error
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
At the end of a request, the request context is popped and all data
|
||||||
|
associated with it is destroyed. If an error occurs during development,
|
||||||
|
it is useful to delay destroying the data for debugging purposes.
|
||||||
|
|
||||||
|
When the development server is running in development mode (the
|
||||||
|
``FLASK_ENV`` environment variable is set to ``'development'``), the
|
||||||
|
error and data will be preserved and shown in the interactive debugger.
|
||||||
|
|
||||||
|
This behavior can be controlled with the
|
||||||
|
:data:`PRESERVE_CONTEXT_ON_EXCEPTION` config. As described above, it
|
||||||
|
defaults to ``True`` in the development environment.
|
||||||
|
|
||||||
|
Do not enable :data:`PRESERVE_CONTEXT_ON_EXCEPTION` in production, as it
|
||||||
|
will cause your application to leak memory on exceptions.
|
||||||
|
|
||||||
Keep in mind that teardown callbacks are always executed, even if
|
|
||||||
before-request callbacks were not executed yet but an exception happened.
|
|
||||||
Certain parts of the test system might also temporarily create a request
|
|
||||||
context without calling the before-request handlers. Make sure to write
|
|
||||||
your teardown-request handlers in a way that they will never fail.
|
|
||||||
|
|
||||||
.. _notes-on-proxies:
|
.. _notes-on-proxies:
|
||||||
|
|
||||||
Notes On Proxies
|
Notes On Proxies
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
Some of the objects provided by Flask are proxies to other objects. The
|
Some of the objects provided by Flask are proxies to other objects. The
|
||||||
reason behind this is that these proxies are shared between threads and
|
proxies are accessed in the same way for each worker thread, but
|
||||||
they have to dispatch to the actual object bound to a thread behind the
|
point to the unique object bound to each worker behind the scenes as
|
||||||
scenes as necessary.
|
described on this page.
|
||||||
|
|
||||||
Most of the time you don't have to care about that, but there are some
|
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 an actual proxy:
|
exceptions where it is good to know that this object is an actual proxy:
|
||||||
|
|
||||||
- The proxy objects do not fake their inherited types, so if you want to
|
- The proxy objects cannot fake their type as the actual object types.
|
||||||
perform actual instance checks, you have to do that on the instance
|
If you want to perform instance checks, you have to do that on the
|
||||||
that is being proxied (see `_get_current_object` below).
|
object being proxied.
|
||||||
- if the object reference is important (so for example for sending
|
- If the specific object reference is important, for example for
|
||||||
:ref:`signals`)
|
sending :ref:`signals` or passing data to a background thread.
|
||||||
|
|
||||||
If you need to get access to the underlying object that is proxied, you
|
If you need to access the underlying object that is proxied, use the
|
||||||
can use the :meth:`~werkzeug.local.LocalProxy._get_current_object` method::
|
:meth:`~werkzeug.local.LocalProxy._get_current_object` method::
|
||||||
|
|
||||||
app = current_app._get_current_object()
|
app = current_app._get_current_object()
|
||||||
my_signal.send(app)
|
my_signal.send(app)
|
||||||
|
|
||||||
Context Preservation on Error
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
If an error occurs or not, at the end of the request the request context
|
|
||||||
is popped and all data associated with it is destroyed. During
|
|
||||||
development however that can be problematic as you might want to have the
|
|
||||||
information around for a longer time in case an exception occurred. In
|
|
||||||
Flask 0.6 and earlier in debug mode, if an exception occurred, the
|
|
||||||
request context was not popped so that the interactive debugger can still
|
|
||||||
provide you with important information.
|
|
||||||
|
|
||||||
Starting with Flask 0.7 you have finer control over that behavior by
|
|
||||||
setting the ``PRESERVE_CONTEXT_ON_EXCEPTION`` configuration variable. By
|
|
||||||
default it's linked to the setting of ``DEBUG``. If the application is in
|
|
||||||
debug mode the context is preserved. If debug mode is set to off, the context
|
|
||||||
is not preserved.
|
|
||||||
|
|
||||||
Do not force activate ``PRESERVE_CONTEXT_ON_EXCEPTION`` if debug mode is set to off
|
|
||||||
as it will cause your application to leak memory on exceptions. However,
|
|
||||||
it can be useful during development to get the same error preserving
|
|
||||||
behavior as debug mode when attempting to debug an error that
|
|
||||||
only occurs under production settings.
|
|
||||||
|
|
|
||||||
163
flask/app.py
163
flask/app.py
|
|
@ -2106,15 +2106,25 @@ class Flask(_PackageBoundObject):
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def do_teardown_request(self, exc=_sentinel):
|
def do_teardown_request(self, exc=_sentinel):
|
||||||
"""Called after the actual request dispatching and will
|
"""Called after the request is dispatched and the response is
|
||||||
call every as :meth:`teardown_request` decorated function. This is
|
returned, right before the request context is popped.
|
||||||
not actually called by the :class:`Flask` object itself but is always
|
|
||||||
triggered when the request context is popped. That way we have a
|
This calls all functions decorated with
|
||||||
tighter control over certain resources under testing environments.
|
:meth:`teardown_request`, and :meth:`Blueprint.teardown_request`
|
||||||
|
if a blueprint handled the request. Finally, the
|
||||||
|
:data:`request_tearing_down` signal is sent.
|
||||||
|
|
||||||
|
This is called by
|
||||||
|
:meth:`RequestContext.pop() <flask.ctx.RequestContext.pop>`,
|
||||||
|
which may be delayed during testing to maintain access to
|
||||||
|
resources.
|
||||||
|
|
||||||
|
:param exc: An unhandled exception raised while dispatching the
|
||||||
|
request. Detected from the current exception information if
|
||||||
|
not passed. Passed to each teardown function.
|
||||||
|
|
||||||
.. versionchanged:: 0.9
|
.. versionchanged:: 0.9
|
||||||
Added the `exc` argument. Previously this was always using the
|
Added the ``exc`` argument.
|
||||||
current exception information.
|
|
||||||
"""
|
"""
|
||||||
if exc is _sentinel:
|
if exc is _sentinel:
|
||||||
exc = sys.exc_info()[1]
|
exc = sys.exc_info()[1]
|
||||||
|
|
@ -2127,9 +2137,17 @@ class Flask(_PackageBoundObject):
|
||||||
request_tearing_down.send(self, exc=exc)
|
request_tearing_down.send(self, exc=exc)
|
||||||
|
|
||||||
def do_teardown_appcontext(self, exc=_sentinel):
|
def do_teardown_appcontext(self, exc=_sentinel):
|
||||||
"""Called when an application context is popped. This works pretty
|
"""Called right before the application context is popped.
|
||||||
much the same as :meth:`do_teardown_request` but for the application
|
|
||||||
context.
|
When handling a request, the application context is popped
|
||||||
|
after the request context. See :meth:`do_teardown_request`.
|
||||||
|
|
||||||
|
This calls all functions decorated with
|
||||||
|
:meth:`teardown_appcontext`. Then the
|
||||||
|
:data:`appcontext_tearing_down` signal is sent.
|
||||||
|
|
||||||
|
This is called by
|
||||||
|
:meth:`AppContext.pop() <flask.ctx.AppContext.pop>`.
|
||||||
|
|
||||||
.. versionadded:: 0.9
|
.. versionadded:: 0.9
|
||||||
"""
|
"""
|
||||||
|
|
@ -2140,62 +2158,89 @@ class Flask(_PackageBoundObject):
|
||||||
appcontext_tearing_down.send(self, exc=exc)
|
appcontext_tearing_down.send(self, exc=exc)
|
||||||
|
|
||||||
def app_context(self):
|
def app_context(self):
|
||||||
"""Binds the application only. For as long as the application is bound
|
"""Create an :class:`~flask.ctx.AppContext`. Use as a ``with``
|
||||||
to the current context the :data:`flask.current_app` points to that
|
block to push the context, which will make :data:`current_app`
|
||||||
application. An application context is automatically created when a
|
point at this application.
|
||||||
request context is pushed if necessary.
|
|
||||||
|
|
||||||
Example usage::
|
An application context is automatically pushed by
|
||||||
|
:meth:`RequestContext.push() <flask.ctx.RequestContext.push>`
|
||||||
|
when handling a request, and when running a CLI command. Use
|
||||||
|
this to manually create a context outside of these situations.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
...
|
init_db()
|
||||||
|
|
||||||
|
See :doc:`/appcontext`.
|
||||||
|
|
||||||
.. versionadded:: 0.9
|
.. versionadded:: 0.9
|
||||||
"""
|
"""
|
||||||
return AppContext(self)
|
return AppContext(self)
|
||||||
|
|
||||||
def request_context(self, environ):
|
def request_context(self, environ):
|
||||||
"""Creates a :class:`~flask.ctx.RequestContext` from the given
|
"""Create a :class:`~flask.ctx.RequestContext` representing a
|
||||||
environment and binds it to the current context. This must be used in
|
WSGI environment. Use a ``with`` block to push the context,
|
||||||
combination with the ``with`` statement because the request is only bound
|
which will make :data:`request` point at this request.
|
||||||
to the current context for the duration of the ``with`` block.
|
|
||||||
|
|
||||||
Example usage::
|
See :doc:`/reqcontext`.
|
||||||
|
|
||||||
with app.request_context(environ):
|
Typically you should not call this from your own code. A request
|
||||||
do_something_with(request)
|
context is automatically pushed by the :meth:`wsgi_app` when
|
||||||
|
handling a request. Use :meth:`test_request_context` to create
|
||||||
The object returned can also be used without the ``with`` statement
|
an environment and context instead of this method.
|
||||||
which is useful for working in the shell. The example above is
|
|
||||||
doing exactly the same as this code::
|
|
||||||
|
|
||||||
ctx = app.request_context(environ)
|
|
||||||
ctx.push()
|
|
||||||
try:
|
|
||||||
do_something_with(request)
|
|
||||||
finally:
|
|
||||||
ctx.pop()
|
|
||||||
|
|
||||||
.. versionchanged:: 0.3
|
|
||||||
Added support for non-with statement usage and ``with`` statement
|
|
||||||
is now passed the ctx object.
|
|
||||||
|
|
||||||
:param environ: a WSGI environment
|
:param environ: a WSGI environment
|
||||||
"""
|
"""
|
||||||
return RequestContext(self, environ)
|
return RequestContext(self, environ)
|
||||||
|
|
||||||
def test_request_context(self, *args, **kwargs):
|
def test_request_context(self, *args, **kwargs):
|
||||||
"""Creates a :class:`~flask.ctx.RequestContext` from the given values
|
"""Create a :class:`~flask.ctx.RequestContext` for a WSGI
|
||||||
(see :class:`werkzeug.test.EnvironBuilder` for more information, this
|
environment created from the given values. This is mostly useful
|
||||||
function accepts the same arguments plus two additional).
|
during testing, where you may want to run a function that uses
|
||||||
|
request data without dispatching a full request.
|
||||||
|
|
||||||
Additional arguments (only if ``base_url`` is not specified):
|
See :doc:`/reqcontext`.
|
||||||
|
|
||||||
:param subdomain: subdomain to use for route matching
|
Use a ``with`` block to push the context, which will make
|
||||||
:param url_scheme: scheme for the request, default
|
:data:`request` point at the request for the created
|
||||||
``PREFERRED_URL_SCHEME`` or ``http``.
|
environment. ::
|
||||||
|
|
||||||
|
with test_request_context(...):
|
||||||
|
generate_report()
|
||||||
|
|
||||||
|
When using the shell, it may be easier to push and pop the
|
||||||
|
context manually to avoid indentation. ::
|
||||||
|
|
||||||
|
ctx = app.test_request_context(...)
|
||||||
|
ctx.push()
|
||||||
|
...
|
||||||
|
ctx.pop()
|
||||||
|
|
||||||
|
Takes the same arguments as Werkzeug's
|
||||||
|
:class:`~werkzeug.test.EnvironBuilder`, with some defaults from
|
||||||
|
the application. See the linked Werkzeug docs for most of the
|
||||||
|
available arguments. Flask-specific behavior is listed here.
|
||||||
|
|
||||||
|
:param path: URL path being requested.
|
||||||
|
:param base_url: Base URL where the app is being served, which
|
||||||
|
``path`` is relative to. If not given, built from
|
||||||
|
:data:`PREFERRED_URL_SCHEME`, ``subdomain``,
|
||||||
|
:data:`SERVER_NAME`, and :data:`APPLICATION_ROOT`.
|
||||||
|
:param subdomain: Subdomain name to append to
|
||||||
|
:data:`SERVER_NAME`.
|
||||||
|
:param url_scheme: Scheme to use instead of
|
||||||
|
:data:`PREFERRED_URL_SCHEME`.
|
||||||
|
:param data: The request body, either as a string or a dict of
|
||||||
|
form keys and values.
|
||||||
|
:param json: If given, this is serialized as JSON and passed as
|
||||||
|
``data``. Also defaults ``content_type`` to
|
||||||
|
``application/json``.
|
||||||
|
:param args: other positional arguments passed to
|
||||||
|
:class:`~werkzeug.test.EnvironBuilder`.
|
||||||
|
:param kwargs: other keyword arguments passed to
|
||||||
|
:class:`~werkzeug.test.EnvironBuilder`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from flask.testing import make_test_environ_builder
|
from flask.testing import make_test_environ_builder
|
||||||
|
|
||||||
builder = make_test_environ_builder(self, *args, **kwargs)
|
builder = make_test_environ_builder(self, *args, **kwargs)
|
||||||
|
|
@ -2206,9 +2251,9 @@ class Flask(_PackageBoundObject):
|
||||||
builder.close()
|
builder.close()
|
||||||
|
|
||||||
def wsgi_app(self, environ, start_response):
|
def wsgi_app(self, environ, start_response):
|
||||||
"""The actual WSGI application. This is not implemented in
|
"""The actual WSGI application. This is not implemented in
|
||||||
`__call__` so that middlewares can be applied without losing a
|
:meth:`__call__` so that middlewares can be applied without
|
||||||
reference to the class. So instead of doing this::
|
losing a reference to the app object. Instead of doing this::
|
||||||
|
|
||||||
app = MyMiddleware(app)
|
app = MyMiddleware(app)
|
||||||
|
|
||||||
|
|
@ -2220,15 +2265,15 @@ class Flask(_PackageBoundObject):
|
||||||
can continue to call methods on it.
|
can continue to call methods on it.
|
||||||
|
|
||||||
.. versionchanged:: 0.7
|
.. versionchanged:: 0.7
|
||||||
The behavior of the before and after request callbacks was changed
|
Teardown events for the request and app contexts are called
|
||||||
under error conditions and a new callback was added that will
|
even if an unhandled error occurs. Other events may not be
|
||||||
always execute at the end of the request, independent on if an
|
called depending on when an error occurs during dispatch.
|
||||||
error occurred or not. See :ref:`callbacks-and-errors`.
|
See :ref:`callbacks-and-errors`.
|
||||||
|
|
||||||
:param environ: a WSGI environment
|
:param environ: A WSGI environment.
|
||||||
:param start_response: a callable accepting a status code,
|
:param start_response: A callable accepting a status code,
|
||||||
a list of headers and an optional
|
a list of headers, and an optional exception context to
|
||||||
exception context to start the response
|
start the response.
|
||||||
"""
|
"""
|
||||||
ctx = self.request_context(environ)
|
ctx = self.request_context(environ)
|
||||||
error = None
|
error = None
|
||||||
|
|
@ -2249,7 +2294,9 @@ class Flask(_PackageBoundObject):
|
||||||
ctx.auto_pop(error)
|
ctx.auto_pop(error)
|
||||||
|
|
||||||
def __call__(self, environ, start_response):
|
def __call__(self, environ, start_response):
|
||||||
"""Shortcut for :attr:`wsgi_app`."""
|
"""The WSGI server calls the Flask application object as the
|
||||||
|
WSGI application. This calls :meth:`wsgi_app` which can be
|
||||||
|
wrapped to applying middleware."""
|
||||||
return self.wsgi_app(environ, start_response)
|
return self.wsgi_app(environ, start_response)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
|
|
||||||
44
flask/ctx.py
44
flask/ctx.py
|
|
@ -24,18 +24,60 @@ _sentinel = object()
|
||||||
|
|
||||||
|
|
||||||
class _AppCtxGlobals(object):
|
class _AppCtxGlobals(object):
|
||||||
"""A plain object."""
|
"""A plain object. Used as a namespace for storing data during an
|
||||||
|
application context.
|
||||||
|
|
||||||
|
Creating an app context automatically creates this object, which is
|
||||||
|
made available as the :data:`g` proxy.
|
||||||
|
|
||||||
|
.. describe:: 'key' in g
|
||||||
|
|
||||||
|
Check whether an attribute is present.
|
||||||
|
|
||||||
|
.. versionadded:: 0.10
|
||||||
|
|
||||||
|
.. describe:: iter(g)
|
||||||
|
|
||||||
|
Return an iterator over the attribute names.
|
||||||
|
|
||||||
|
.. versionadded:: 0.10
|
||||||
|
"""
|
||||||
|
|
||||||
def get(self, name, default=None):
|
def get(self, name, default=None):
|
||||||
|
"""Get an attribute by name, or a default value. Like
|
||||||
|
:meth:`dict.get`.
|
||||||
|
|
||||||
|
:param name: Name of attribute to get.
|
||||||
|
:param default: Value to return if the attribute is not present.
|
||||||
|
|
||||||
|
.. versionadded:: 0.10
|
||||||
|
"""
|
||||||
return self.__dict__.get(name, default)
|
return self.__dict__.get(name, default)
|
||||||
|
|
||||||
def pop(self, name, default=_sentinel):
|
def pop(self, name, default=_sentinel):
|
||||||
|
"""Get and remove an attribute by name. Like :meth:`dict.pop`.
|
||||||
|
|
||||||
|
:param name: Name of attribute to pop.
|
||||||
|
:param default: Value to return if the attribute is not present,
|
||||||
|
instead of raise a ``KeyError``.
|
||||||
|
|
||||||
|
.. versionadded:: 0.11
|
||||||
|
"""
|
||||||
if default is _sentinel:
|
if default is _sentinel:
|
||||||
return self.__dict__.pop(name)
|
return self.__dict__.pop(name)
|
||||||
else:
|
else:
|
||||||
return self.__dict__.pop(name, default)
|
return self.__dict__.pop(name, default)
|
||||||
|
|
||||||
def setdefault(self, name, default=None):
|
def setdefault(self, name, default=None):
|
||||||
|
"""Get the value of an attribute if it is present, otherwise
|
||||||
|
set and return a default value. Like :meth:`dict.setdefault`.
|
||||||
|
|
||||||
|
:param name: Name of attribute to get.
|
||||||
|
:param: default: Value to set and return if the attribute is not
|
||||||
|
present.
|
||||||
|
|
||||||
|
.. versionadded:: 0.11
|
||||||
|
"""
|
||||||
return self.__dict__.setdefault(name, default)
|
return self.__dict__.setdefault(name, default)
|
||||||
|
|
||||||
def __contains__(self, item):
|
def __contains__(self, item):
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ _app_ctx_err_msg = '''\
|
||||||
Working outside of application context.
|
Working outside of application context.
|
||||||
|
|
||||||
This typically means that you attempted to use functionality that needed
|
This typically means that you attempted to use functionality that needed
|
||||||
to interface with the current application object in a way. To solve
|
to interface with the current application object in some way. To solve
|
||||||
this set up an application context with app.app_context(). See the
|
this, set up an application context with app.app_context(). See the
|
||||||
documentation for more information.\
|
documentation for more information.\
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,26 @@ def make_test_environ_builder(
|
||||||
app, path='/', base_url=None, subdomain=None, url_scheme=None,
|
app, path='/', base_url=None, subdomain=None, url_scheme=None,
|
||||||
*args, **kwargs
|
*args, **kwargs
|
||||||
):
|
):
|
||||||
"""Creates a new test builder with some application defaults thrown in."""
|
"""Create a :class:`~werkzeug.test.EnvironBuilder`, taking some
|
||||||
|
defaults from the application.
|
||||||
|
|
||||||
|
:param app: The Flask application to configure the environment from.
|
||||||
|
:param path: URL path being requested.
|
||||||
|
:param base_url: Base URL where the app is being served, which
|
||||||
|
``path`` is relative to. If not given, built from
|
||||||
|
:data:`PREFERRED_URL_SCHEME`, ``subdomain``,
|
||||||
|
:data:`SERVER_NAME`, and :data:`APPLICATION_ROOT`.
|
||||||
|
:param subdomain: Subdomain name to append to :data:`SERVER_NAME`.
|
||||||
|
:param url_scheme: Scheme to use instead of
|
||||||
|
:data:`PREFERRED_URL_SCHEME`.
|
||||||
|
:param json: If given, this is serialized as JSON and passed as
|
||||||
|
``data``. Also defaults ``content_type`` to
|
||||||
|
``application/json``.
|
||||||
|
:param args: other positional arguments passed to
|
||||||
|
:class:`~werkzeug.test.EnvironBuilder`.
|
||||||
|
:param kwargs: other keyword arguments passed to
|
||||||
|
:class:`~werkzeug.test.EnvironBuilder`.
|
||||||
|
"""
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
not (base_url or subdomain or url_scheme)
|
not (base_url or subdomain or url_scheme)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue