rework context docs
This commit is contained in:
parent
47a00864c3
commit
2411707492
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
|
||||
|
||||
Just store on this whatever you want. For example a database
|
||||
connection or the user that is currently logged in.
|
||||
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`.
|
||||
|
||||
Starting with Flask 0.10 this is stored on the application context and
|
||||
no longer on the request context which means it becomes available if
|
||||
only the application context is bound and not yet a request. This
|
||||
is especially useful when combined with the :ref:`faking-resources`
|
||||
pattern for testing.
|
||||
This is a good place to store resources during a request. During
|
||||
testing, you can use the :ref:`faking-resources` pattern to
|
||||
pre-configure such resources.
|
||||
|
||||
Additionally as of 0.10 you can use the :meth:`get` method to
|
||||
get an attribute or ``None`` (or the second argument) if it's not set.
|
||||
These two usages are now equivalent::
|
||||
This is a proxy. See :ref:`notes-on-proxies` for more information.
|
||||
|
||||
user = getattr(flask.g, 'user', None)
|
||||
user = flask.g.get('user', None)
|
||||
.. versionchanged:: 0.10
|
||||
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
|
||||
attribute is defined and it yields all keys on iteration.
|
||||
|
||||
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.
|
||||
.. autoclass:: flask.ctx._AppCtxGlobals
|
||||
:members:
|
||||
|
||||
|
||||
Useful Functions and Classes
|
||||
|
|
@ -241,13 +234,17 @@ Useful Functions and Classes
|
|||
|
||||
.. data:: current_app
|
||||
|
||||
Points to the application handling the request. This is useful for
|
||||
extensions that want to support multiple applications running side
|
||||
by side. This is powered by the application context and not by the
|
||||
request context, so you can change the value of this proxy by
|
||||
using the :meth:`~flask.Flask.app_context` method.
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
|
|
@ -384,50 +381,54 @@ Useful Internals
|
|||
|
||||
.. data:: _request_ctx_stack
|
||||
|
||||
The internal :class:`~werkzeug.local.LocalStack` that is used to implement
|
||||
all the context local objects used in Flask. This is a documented
|
||||
instance and can be used by extensions and application code but the
|
||||
use is discouraged in general.
|
||||
The internal :class:`~werkzeug.local.LocalStack` that holds
|
||||
:class:`~flask.ctx.RequestContext` instances. Typically, the
|
||||
:data:`request` and :data:`session` proxies should be accessed
|
||||
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
|
||||
stack:
|
||||
The following attributes are always present on each layer of the
|
||||
stack:
|
||||
|
||||
`app`
|
||||
`app`
|
||||
the active Flask application.
|
||||
|
||||
`url_adapter`
|
||||
`url_adapter`
|
||||
the URL adapter that was used to match the request.
|
||||
|
||||
`request`
|
||||
`request`
|
||||
the current request object.
|
||||
|
||||
`session`
|
||||
`session`
|
||||
the active session object.
|
||||
|
||||
`g`
|
||||
`g`
|
||||
an object with all the attributes of the :data:`flask.g` object.
|
||||
|
||||
`flashes`
|
||||
`flashes`
|
||||
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():
|
||||
ctx = _request_ctx_stack.top
|
||||
if ctx is not None:
|
||||
return ctx.session
|
||||
def get_session():
|
||||
ctx = _request_ctx_stack.top
|
||||
if ctx is not None:
|
||||
return ctx.session
|
||||
|
||||
.. autoclass:: flask.ctx.AppContext
|
||||
:members:
|
||||
|
||||
.. data:: _app_ctx_stack
|
||||
|
||||
Works similar to the request context but only binds the application.
|
||||
This is mainly there for extensions to store data.
|
||||
The internal :class:`~werkzeug.local.LocalStack` that holds
|
||||
: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
|
||||
:members:
|
||||
|
|
|
|||
|
|
@ -1,144 +1,159 @@
|
|||
.. currentmodule:: flask
|
||||
|
||||
.. _app-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
|
||||
different “states” in which code is executed:
|
||||
This is similar to the :doc:`/reqcontext`, which keeps track of
|
||||
request-level data during a request. A corresponding application context
|
||||
is pushed when a request context is pushed.
|
||||
|
||||
1. The application setup state, in which the application implicitly is
|
||||
on the module level.
|
||||
Purpose of the Context
|
||||
----------------------
|
||||
|
||||
This state starts when the :class:`Flask` object is instantiated, and
|
||||
it implicitly ends when the first request comes in. While the
|
||||
application is in this state, a few assumptions are true:
|
||||
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 programmer can modify the application object safely.
|
||||
- no request handling happened so far
|
||||
- you have to have a reference to the application object in order to
|
||||
modify it, there is no magic proxy that can give you a reference to
|
||||
the application object you're currently creating or modifying.
|
||||
Flask solves this issue with the *application context*. Rather than
|
||||
referring to an ``app`` directly, you use the the :data:`current_app`
|
||||
proxy, which points to the application handling the current activity.
|
||||
|
||||
2. In contrast, in the request handling state, a couple of other rules
|
||||
exist:
|
||||
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`.
|
||||
|
||||
- while a request is active, the context local objects
|
||||
(:data:`flask.request` and others) point to the current request.
|
||||
- any code can get hold of these objects at any time.
|
||||
Flask will also automatically push an app context when running CLI
|
||||
commands registered with :attr:`Flask.cli` using ``@app.cli.command()``.
|
||||
|
||||
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
|
||||
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.
|
||||
Lifetime of the Context
|
||||
-----------------------
|
||||
|
||||
The application context is what powers the :data:`~flask.current_app`
|
||||
context local.
|
||||
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.
|
||||
|
||||
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
|
||||
recommended passing applications around explicitly, but that caused issues
|
||||
with libraries that were not designed with that in mind.
|
||||
Manually Push a Context
|
||||
-----------------------
|
||||
|
||||
A common workaround for that problem was to use the
|
||||
:data:`~flask.current_app` proxy later on, which was bound to the current
|
||||
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.
|
||||
If you try to access :data:`current_app`, or anything that uses it,
|
||||
outside an application context, you'll get this error message:
|
||||
|
||||
Creating an Application Context
|
||||
-------------------------------
|
||||
|
||||
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. ::
|
||||
.. code-block:: pytb
|
||||
|
||||
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
|
||||
moves between threads and it will not be shared between requests. As such
|
||||
it is the perfect place to store database connection information and other
|
||||
things. The internal stack object is called :data:`flask._app_ctx_stack`.
|
||||
Extensions are free to store additional information on the topmost level,
|
||||
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.
|
||||
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`. ::
|
||||
|
||||
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
|
||||
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.
|
||||
return app
|
||||
|
||||
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
|
||||
``X`` if it does not exist yet and otherwise returns the same resource,
|
||||
and a ``teardown_X()`` function that is registered as teardown handler.
|
||||
Storing Data
|
||||
------------
|
||||
|
||||
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
|
||||
|
||||
def get_db():
|
||||
db = getattr(g, '_database', None)
|
||||
if db is None:
|
||||
db = g._database = connect_to_database()
|
||||
return db
|
||||
if 'db' not in g:
|
||||
g.db = connect_to_database()
|
||||
|
||||
return g.db
|
||||
|
||||
@app.teardown_appcontext
|
||||
def teardown_db(exception):
|
||||
db = getattr(g, '_database', None)
|
||||
def teardown_db():
|
||||
db = g.pop('db', None)
|
||||
|
||||
if db is not None:
|
||||
db.close()
|
||||
|
||||
The first time ``get_db()`` is called the connection will be established.
|
||||
To make this implicit a :class:`~werkzeug.local.LocalProxy` can be used::
|
||||
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)
|
||||
|
||||
That way a user can directly access ``db`` which internally calls
|
||||
``get_db()``.
|
||||
Accessing ``db`` will call ``get_db`` internally, in the same way that
|
||||
:data:`current_app` works.
|
||||
|
||||
----
|
||||
|
||||
If you're writing an extension, :data:`g` should be reserved for user
|
||||
code. You may store internal data on the context itself, but be sure to
|
||||
use a sufficiently unique name. The current context is accessed with
|
||||
:data:`_app_ctx_stack.top <_app_ctx_stack>`. For more information see
|
||||
:doc:`extensiondev`.
|
||||
|
||||
|
||||
Events and Signals
|
||||
------------------
|
||||
|
||||
The application will call functions registered with
|
||||
:meth:`~Flask.teardown_appcontext` when the application context is
|
||||
popped.
|
||||
|
||||
If :data:`~signals.signals_available` is true, the following signals are
|
||||
sent: :data:`appcontext_pushed`, :data:`appcontext_tearing_down`, and
|
||||
:data:`appcontext_popped`.
|
||||
|
|
|
|||
|
|
@ -1,224 +1,267 @@
|
|||
.. currentmodule:: flask
|
||||
|
||||
.. _request-context:
|
||||
|
||||
The Request Context
|
||||
===================
|
||||
|
||||
This document describes the behavior in Flask 0.7 which is mostly in line
|
||||
with the old behavior but has some small, subtle differences.
|
||||
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.
|
||||
|
||||
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
|
||||
redirected to. Imagine it would always redirect to the URL's ``next``
|
||||
parameter or the HTTP referrer or the index page::
|
||||
Purpose of the Context
|
||||
----------------------
|
||||
|
||||
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():
|
||||
return request.args.get('next') or \
|
||||
request.referrer or \
|
||||
url_for('index')
|
||||
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.
|
||||
|
||||
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()
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
AttributeError: 'NoneType' object has no attribute 'request'
|
||||
Lifetime of the Context
|
||||
-----------------------
|
||||
|
||||
That makes a lot of sense because we currently do not have a request we
|
||||
could access. So we have to make a request and bind it to the current
|
||||
context. The :attr:`~flask.Flask.test_request_context` method can create
|
||||
us a :class:`~flask.ctx.RequestContext`:
|
||||
When a Flask application begins handling a request, it pushes a request
|
||||
context, which also pushes an :doc:`/appcontext`. When the request ends
|
||||
it pops the request context then the application context.
|
||||
|
||||
>>> 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
|
||||
or by calling the :meth:`~flask.ctx.RequestContext.push` and
|
||||
:meth:`~flask.ctx.RequestContext.pop` methods:
|
||||
Context locals are implemented in Werkzeug. See :doc:`werkzeug:local`
|
||||
for more information on how this works internally.
|
||||
|
||||
>>> ctx.push()
|
||||
|
||||
From that point onwards you can work with the request object:
|
||||
Manually Push a Context
|
||||
-----------------------
|
||||
|
||||
>>> redirect_url()
|
||||
u'http://example.com/'
|
||||
If you try to access :data:`request`, or anything that uses it, outside
|
||||
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
|
||||
push and pop multiple times. This is very handy to implement things like
|
||||
internal redirects.
|
||||
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', 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
|
||||
---------------------
|
||||
|
||||
If you look into how the Flask WSGI application internally works, you will
|
||||
find a piece of code that looks very much like this::
|
||||
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 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):
|
||||
with self.request_context(environ):
|
||||
try:
|
||||
response = self.full_dispatch_request()
|
||||
except Exception as e:
|
||||
response = self.make_response(self.handle_exception(e))
|
||||
return response(environ, start_response)
|
||||
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.
|
||||
|
||||
The method :meth:`~Flask.request_context` returns a new
|
||||
:class:`~flask.ctx.RequestContext` object and uses it in combination with
|
||||
the ``with`` statement to bind the context. Everything that is called from
|
||||
the same thread from this point onwards until the end of the ``with``
|
||||
statement will have access to the request globals (:data:`flask.request`
|
||||
and others).
|
||||
Because the contexts are stacks, 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.
|
||||
|
||||
The request context internally works like a stack: The topmost level on
|
||||
the stack is the current active request.
|
||||
:meth:`~flask.ctx.RequestContext.push` adds the context to the stack on
|
||||
the very top, :meth:`~flask.ctx.RequestContext.pop` removes it from the
|
||||
stack again. On popping the application's
|
||||
:func:`~flask.Flask.teardown_request` functions are also executed.
|
||||
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 are executed. These
|
||||
execute even if an unhandled exception occurred during dispatch.
|
||||
|
||||
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
|
||||
--------------------
|
||||
|
||||
What happens if an error occurs in Flask during request processing? This
|
||||
particular behavior changed in 0.7 because we wanted to make it easier to
|
||||
understand what is actually happening. The new behavior is quite simple:
|
||||
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.
|
||||
|
||||
1. Before each request, :meth:`~flask.Flask.before_request` functions are
|
||||
executed. If one of these functions return a response, the other
|
||||
functions are no longer called. In any case however the return value
|
||||
is treated as a replacement for the view's return value.
|
||||
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.
|
||||
|
||||
2. If the :meth:`~flask.Flask.before_request` functions did not return a
|
||||
response, the regular request handling kicks in and the view function
|
||||
that was matched has the chance to return a response.
|
||||
#. 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.
|
||||
|
||||
3. The return value of the view is then converted into an actual response
|
||||
object and handed over to the :meth:`~flask.Flask.after_request`
|
||||
functions which have the chance to replace it or modify it in place.
|
||||
#. 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.
|
||||
|
||||
4. At the end of the request the :meth:`~flask.Flask.teardown_request`
|
||||
functions are executed. This always happens, even in case of an
|
||||
unhandled exception down the road or if a before-request handler was
|
||||
not executed yet or at all (for example in test environments sometimes
|
||||
you might want to not execute before-request callbacks).
|
||||
#. 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.
|
||||
|
||||
Now what happens on errors? If you are not in debug mode and an exception is not
|
||||
caught, the 500 internal server handler is called. In debug mode
|
||||
however the exception is not further processed and bubbles up to the WSGI
|
||||
server. That way things like the interactive debugger can provide helpful
|
||||
debug information.
|
||||
#. 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.
|
||||
|
||||
An important change in 0.7 is that the internal server error is now no
|
||||
longer post processed by the after request callbacks and after request
|
||||
callbacks are no longer guaranteed to be executed. This way the internal
|
||||
dispatching code looks cleaner and is easier to customize and understand.
|
||||
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.
|
||||
|
||||
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
|
||||
------------------
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The teardown callbacks are special callbacks in that they are executed at
|
||||
a different point. Strictly speaking they are independent of the actual
|
||||
request handling as they are bound to the lifecycle of the
|
||||
:class:`~flask.ctx.RequestContext` object. When the request context is
|
||||
popped, the :meth:`~flask.Flask.teardown_request` functions are called.
|
||||
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.
|
||||
|
||||
This is important to know if the life of the request context is prolonged
|
||||
by using the test client in a with statement or when using the request
|
||||
context from the command line::
|
||||
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.
|
||||
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:
|
||||
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
|
||||
.. code-block:: python
|
||||
|
||||
# only when the code reaches this point the teardown functions
|
||||
# are called. Alternatively the same thing happens if another
|
||||
# request was triggered from the test client
|
||||
from flask import Flask, request
|
||||
|
||||
It's easy to see the behavior from the command line:
|
||||
app = Flask(__name__)
|
||||
|
||||
>>> app = Flask(__name__)
|
||||
>>> @app.teardown_request
|
||||
... def teardown_request(exception=None):
|
||||
... print 'this runs after request'
|
||||
...
|
||||
>>> ctx = app.test_request_context()
|
||||
>>> ctx.push()
|
||||
>>> ctx.pop()
|
||||
this runs after request
|
||||
>>>
|
||||
@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():
|
||||
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
|
||||
----------------
|
||||
|
||||
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
|
||||
they have to dispatch to the actual object bound to a thread behind the
|
||||
scenes as necessary.
|
||||
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 an actual proxy:
|
||||
|
||||
- The proxy objects do not fake their inherited types, so if you want to
|
||||
perform actual instance checks, you have to do that on the instance
|
||||
that is being proxied (see `_get_current_object` below).
|
||||
- if the object reference is important (so for example for sending
|
||||
:ref:`signals`)
|
||||
- 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.
|
||||
- If the specific object reference is important, for example for
|
||||
sending :ref:`signals` or passing data to a background thread.
|
||||
|
||||
If you need to get access to the underlying object that is proxied, you
|
||||
can use the :meth:`~werkzeug.local.LocalProxy._get_current_object` method::
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
def do_teardown_request(self, exc=_sentinel):
|
||||
"""Called after the actual request dispatching and will
|
||||
call every as :meth:`teardown_request` decorated function. This is
|
||||
not actually called by the :class:`Flask` object itself but is always
|
||||
triggered when the request context is popped. That way we have a
|
||||
tighter control over certain resources under testing environments.
|
||||
"""Called after the request is dispatched and the response is
|
||||
returned, right before the request context is popped.
|
||||
|
||||
This calls all functions decorated with
|
||||
: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
|
||||
Added the `exc` argument. Previously this was always using the
|
||||
current exception information.
|
||||
Added the ``exc`` argument.
|
||||
"""
|
||||
if exc is _sentinel:
|
||||
exc = sys.exc_info()[1]
|
||||
|
|
@ -2127,9 +2137,17 @@ class Flask(_PackageBoundObject):
|
|||
request_tearing_down.send(self, exc=exc)
|
||||
|
||||
def do_teardown_appcontext(self, exc=_sentinel):
|
||||
"""Called when an application context is popped. This works pretty
|
||||
much the same as :meth:`do_teardown_request` but for the application
|
||||
context.
|
||||
"""Called right before the application context is popped.
|
||||
|
||||
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
|
||||
"""
|
||||
|
|
@ -2140,62 +2158,89 @@ class Flask(_PackageBoundObject):
|
|||
appcontext_tearing_down.send(self, exc=exc)
|
||||
|
||||
def app_context(self):
|
||||
"""Binds the application only. For as long as the application is bound
|
||||
to the current context the :data:`flask.current_app` points to that
|
||||
application. An application context is automatically created when a
|
||||
request context is pushed if necessary.
|
||||
"""Create an :class:`~flask.ctx.AppContext`. Use as a ``with``
|
||||
block to push the context, which will make :data:`current_app`
|
||||
point at this application.
|
||||
|
||||
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():
|
||||
...
|
||||
init_db()
|
||||
|
||||
See :doc:`/appcontext`.
|
||||
|
||||
.. versionadded:: 0.9
|
||||
"""
|
||||
return AppContext(self)
|
||||
|
||||
def request_context(self, environ):
|
||||
"""Creates a :class:`~flask.ctx.RequestContext` from the given
|
||||
environment and binds it to the current context. This must be used in
|
||||
combination with the ``with`` statement because the request is only bound
|
||||
to the current context for the duration of the ``with`` block.
|
||||
"""Create a :class:`~flask.ctx.RequestContext` representing a
|
||||
WSGI environment. Use a ``with`` block to push the context,
|
||||
which will make :data:`request` point at this request.
|
||||
|
||||
Example usage::
|
||||
See :doc:`/reqcontext`.
|
||||
|
||||
with app.request_context(environ):
|
||||
do_something_with(request)
|
||||
|
||||
The object returned can also be used without the ``with`` statement
|
||||
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.
|
||||
Typically you should not call this from your own code. A request
|
||||
context is automatically pushed by the :meth:`wsgi_app` when
|
||||
handling a request. Use :meth:`test_request_context` to create
|
||||
an environment and context instead of this method.
|
||||
|
||||
:param environ: a WSGI environment
|
||||
"""
|
||||
return RequestContext(self, environ)
|
||||
|
||||
def test_request_context(self, *args, **kwargs):
|
||||
"""Creates a :class:`~flask.ctx.RequestContext` from the given values
|
||||
(see :class:`werkzeug.test.EnvironBuilder` for more information, this
|
||||
function accepts the same arguments plus two additional).
|
||||
"""Create a :class:`~flask.ctx.RequestContext` for a WSGI
|
||||
environment created from the given values. This is mostly useful
|
||||
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
|
||||
:param url_scheme: scheme for the request, default
|
||||
``PREFERRED_URL_SCHEME`` or ``http``.
|
||||
Use a ``with`` block to push the context, which will make
|
||||
:data:`request` point at the request for the created
|
||||
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
|
||||
|
||||
builder = make_test_environ_builder(self, *args, **kwargs)
|
||||
|
|
@ -2206,9 +2251,9 @@ class Flask(_PackageBoundObject):
|
|||
builder.close()
|
||||
|
||||
def wsgi_app(self, environ, start_response):
|
||||
"""The actual WSGI application. This is not implemented in
|
||||
`__call__` so that middlewares can be applied without losing a
|
||||
reference to the class. So instead of doing this::
|
||||
"""The actual WSGI application. This is not implemented in
|
||||
:meth:`__call__` so that middlewares can be applied without
|
||||
losing a reference to the app object. Instead of doing this::
|
||||
|
||||
app = MyMiddleware(app)
|
||||
|
||||
|
|
@ -2220,15 +2265,15 @@ class Flask(_PackageBoundObject):
|
|||
can continue to call methods on it.
|
||||
|
||||
.. versionchanged:: 0.7
|
||||
The behavior of the before and after request callbacks was changed
|
||||
under error conditions and a new callback was added that will
|
||||
always execute at the end of the request, independent on if an
|
||||
error occurred or not. See :ref:`callbacks-and-errors`.
|
||||
Teardown events for the request and app contexts are called
|
||||
even if an unhandled error occurs. Other events may not be
|
||||
called depending on when an error occurs during dispatch.
|
||||
See :ref:`callbacks-and-errors`.
|
||||
|
||||
:param environ: a WSGI environment
|
||||
:param start_response: a callable accepting a status code,
|
||||
a list of headers and an optional
|
||||
exception context to start the response
|
||||
:param environ: A WSGI environment.
|
||||
:param start_response: A callable accepting a status code,
|
||||
a list of headers, and an optional exception context to
|
||||
start the response.
|
||||
"""
|
||||
ctx = self.request_context(environ)
|
||||
error = None
|
||||
|
|
@ -2249,7 +2294,9 @@ class Flask(_PackageBoundObject):
|
|||
ctx.auto_pop(error)
|
||||
|
||||
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)
|
||||
|
||||
def __repr__(self):
|
||||
|
|
|
|||
44
flask/ctx.py
44
flask/ctx.py
|
|
@ -24,18 +24,60 @@ _sentinel = 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):
|
||||
"""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)
|
||||
|
||||
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:
|
||||
return self.__dict__.pop(name)
|
||||
else:
|
||||
return self.__dict__.pop(name, default)
|
||||
|
||||
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)
|
||||
|
||||
def __contains__(self, item):
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ _app_ctx_err_msg = '''\
|
|||
Working outside of application context.
|
||||
|
||||
This typically means that you attempted to use functionality that needed
|
||||
to interface with the current application object in a way. To solve
|
||||
this set up an application context with app.app_context(). See the
|
||||
to interface with the current application object in some way. To solve
|
||||
this, set up an application context with app.app_context(). See the
|
||||
documentation for more information.\
|
||||
'''
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,26 @@ def make_test_environ_builder(
|
|||
app, path='/', base_url=None, subdomain=None, url_scheme=None,
|
||||
*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 (
|
||||
not (base_url or subdomain or url_scheme)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue