Added notes on proxies
This commit is contained in:
parent
c0abdc4fa5
commit
3b0eb0f3ca
2 changed files with 63 additions and 18 deletions
35
docs/api.rst
35
docs/api.rst
|
|
@ -38,6 +38,8 @@ Incoming Request Data
|
||||||
sure that you always get the correct data for the active thread if you
|
sure that you always get the correct data for the active thread if you
|
||||||
are in a multithreaded environment.
|
are in a multithreaded environment.
|
||||||
|
|
||||||
|
This is a proxy. See :ref:`notes-on-proxies` for more information.
|
||||||
|
|
||||||
The request object is an instance of a :class:`~werkzeug.Request`
|
The request object is an instance of a :class:`~werkzeug.Request`
|
||||||
subclass and provides all of the attributes Werkzeug defines. This
|
subclass and provides all of the attributes Werkzeug defines. This
|
||||||
just shows a quick overview of the most important ones.
|
just shows a quick overview of the most important ones.
|
||||||
|
|
@ -164,6 +166,8 @@ To access the current session you can use the :class:`session` object:
|
||||||
The session object works pretty much like an ordinary dict, with the
|
The session object works pretty much like an ordinary dict, with the
|
||||||
difference that it keeps track on modifications.
|
difference that it keeps track on modifications.
|
||||||
|
|
||||||
|
This is a proxy. See :ref:`notes-on-proxies` for more information.
|
||||||
|
|
||||||
The following attributes are interesting:
|
The following attributes are interesting:
|
||||||
|
|
||||||
.. attribute:: new
|
.. attribute:: new
|
||||||
|
|
@ -206,6 +210,8 @@ thing, like it does for :class:`request` and :class:`session`.
|
||||||
Just store on this whatever you want. For example a database
|
Just store on this whatever you want. For example a database
|
||||||
connection or the user that is currently logged in.
|
connection or the user that is currently logged in.
|
||||||
|
|
||||||
|
This is a proxy. See :ref:`notes-on-proxies` for more information.
|
||||||
|
|
||||||
|
|
||||||
Useful Functions and Classes
|
Useful Functions and Classes
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
@ -216,6 +222,8 @@ Useful Functions and Classes
|
||||||
extensions that want to support multiple applications running side
|
extensions that want to support multiple applications running side
|
||||||
by side.
|
by side.
|
||||||
|
|
||||||
|
This is a proxy. See :ref:`notes-on-proxies` for more information.
|
||||||
|
|
||||||
.. autofunction:: url_for
|
.. autofunction:: url_for
|
||||||
|
|
||||||
.. function:: abort(code)
|
.. function:: abort(code)
|
||||||
|
|
@ -389,6 +397,8 @@ Signals
|
||||||
in debug mode, where no exception handling happens. The exception
|
in debug mode, where no exception handling happens. The exception
|
||||||
itself is passed to the subscriber as `exception`.
|
itself is passed to the subscriber as `exception`.
|
||||||
|
|
||||||
|
.. currentmodule:: None
|
||||||
|
|
||||||
.. class:: flask.signals.Namespace
|
.. class:: flask.signals.Namespace
|
||||||
|
|
||||||
An alias for :class:`blinker.base.Namespace` if blinker is available,
|
An alias for :class:`blinker.base.Namespace` if blinker is available,
|
||||||
|
|
@ -404,3 +414,28 @@ Signals
|
||||||
operations, including connecting.
|
operations, including connecting.
|
||||||
|
|
||||||
.. _blinker: http://pypi.python.org/pypi/blinker
|
.. _blinker: http://pypi.python.org/pypi/blinker
|
||||||
|
|
||||||
|
.. _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.
|
||||||
|
|
||||||
|
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
|
||||||
|
- if the object reference is important (so for example for sending
|
||||||
|
:ref:`signals`)
|
||||||
|
|
||||||
|
If you need to get access to the underlying object that is proxied, you
|
||||||
|
can use the :meth:`~werkzeug.LocalProxy._get_current_object` method::
|
||||||
|
|
||||||
|
app = current_app._get_current_object()
|
||||||
|
my_signal.send(app)
|
||||||
|
|
|
||||||
|
|
@ -41,13 +41,9 @@ the optional second argument specifies a sender. To unsubscribe from a
|
||||||
signal, you can use the :meth:`~blinker.base.Signal.disconnect` method.
|
signal, you can use the :meth:`~blinker.base.Signal.disconnect` method.
|
||||||
|
|
||||||
For all core Flask signals, the sender is the application that issued the
|
For all core Flask signals, the sender is the application that issued the
|
||||||
signal. This however might not be true for Flask extensions, so consult
|
signal. When you subscribe to a signal, be sure to also provide a sender
|
||||||
the documentation when subscribing to signals.
|
unless you really want to listen for signals of all applications. This is
|
||||||
|
especially true if you are developing an extension.
|
||||||
Additionally there is a convenient helper method that allows you to
|
|
||||||
temporarily subscribe a function to a signal. This is especially helpful
|
|
||||||
for unittests (:meth:`~blinker.base.Signal.temporarily_connected_to`).
|
|
||||||
This has to be used in combination with the `with` statement.
|
|
||||||
|
|
||||||
Here for example a helper context manager that can be used to figure out
|
Here for example a helper context manager that can be used to figure out
|
||||||
in a unittest which templates were rendered and what variables were passed
|
in a unittest which templates were rendered and what variables were passed
|
||||||
|
|
@ -57,19 +53,19 @@ to the template::
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def captured_templates():
|
def captured_templates(app):
|
||||||
recorded = []
|
recorded = []
|
||||||
def record(template, context):
|
def record(template, context):
|
||||||
recorded.append((template, context))
|
recorded.append((template, context))
|
||||||
template_rendered.connect(record)
|
template_rendered.connect(record, app)
|
||||||
try:
|
try:
|
||||||
yield recorded
|
yield recorded
|
||||||
finally:
|
finally:
|
||||||
template_rendered.disconnect(record)
|
template_rendered.disconnect(record, app)
|
||||||
|
|
||||||
This can now easily be paired with a test client::
|
This can now easily be paired with a test client::
|
||||||
|
|
||||||
with captured_templates() as templates:
|
with captured_templates(app) as templates:
|
||||||
rv = app.test_client().get('/')
|
rv = app.test_client().get('/')
|
||||||
assert rv.status_code == 200
|
assert rv.status_code == 200
|
||||||
assert len(templates) == 1
|
assert len(templates) == 1
|
||||||
|
|
@ -77,9 +73,23 @@ This can now easily be paired with a test client::
|
||||||
assert template.name == 'index.html'
|
assert template.name == 'index.html'
|
||||||
assert len(context['items']) == 10
|
assert len(context['items']) == 10
|
||||||
|
|
||||||
All the template rendering in the code, the `with` block wraps will now be
|
All the template rendering in the code issued by the application `app`
|
||||||
recorded in the `templates` variable. Whenever a template is rendered,
|
in the body of the `with` block will now be recorded in the `templates`
|
||||||
the template object as well as context is appended to it.
|
variable. Whenever a template is rendered, the template object as well as
|
||||||
|
context are appended to it.
|
||||||
|
|
||||||
|
Additionally there is a convenient helper method
|
||||||
|
(:meth:`~blinker.base.Signal.temporarily_connected_to`). that allows you
|
||||||
|
to temporarily subscribe a function to a signal with is a context manager
|
||||||
|
on its own which simplifies the example above::
|
||||||
|
|
||||||
|
from flask import template_rendered
|
||||||
|
|
||||||
|
def captured_templates(app):
|
||||||
|
recorded = []
|
||||||
|
def record(template, context):
|
||||||
|
recorded.append((template, context))
|
||||||
|
return template_rendered.temporarily_connected_to(record, app)
|
||||||
|
|
||||||
Creating Signals
|
Creating Signals
|
||||||
----------------
|
----------------
|
||||||
|
|
@ -153,7 +163,7 @@ The following signals exist in Flask:
|
||||||
context)
|
context)
|
||||||
|
|
||||||
from flask import request_started
|
from flask import request_started
|
||||||
request_started.connect(log_template_renders)
|
request_started.connect(log_template_renders, app)
|
||||||
|
|
||||||
.. data:: flask.request_started
|
.. data:: flask.request_started
|
||||||
:noindex:
|
:noindex:
|
||||||
|
|
@ -169,7 +179,7 @@ The following signals exist in Flask:
|
||||||
sender.logger.debug('Request context is set up')
|
sender.logger.debug('Request context is set up')
|
||||||
|
|
||||||
from flask import request_started
|
from flask import request_started
|
||||||
request_started.connect(log_request)
|
request_started.connect(log_request, app)
|
||||||
|
|
||||||
.. data:: flask.request_finished
|
.. data:: flask.request_finished
|
||||||
:noindex:
|
:noindex:
|
||||||
|
|
@ -184,7 +194,7 @@ The following signals exist in Flask:
|
||||||
'Response: %s', response)
|
'Response: %s', response)
|
||||||
|
|
||||||
from flask import request_finished
|
from flask import request_finished
|
||||||
request_finished.connect(log_response)
|
request_finished.connect(log_response, app)
|
||||||
|
|
||||||
.. data:: flask.got_request_exception
|
.. data:: flask.got_request_exception
|
||||||
:noindex:
|
:noindex:
|
||||||
|
|
@ -200,6 +210,6 @@ The following signals exist in Flask:
|
||||||
sender.logger.debug('Got exception during processing: %s', exception)
|
sender.logger.debug('Got exception during processing: %s', exception)
|
||||||
|
|
||||||
from flask import got_request_exception
|
from flask import got_request_exception
|
||||||
got_request_exception.connect(log_exception)
|
got_request_exception.connect(log_exception, app)
|
||||||
|
|
||||||
.. _blinker: http://pypi.python.org/pypi/blinker
|
.. _blinker: http://pypi.python.org/pypi/blinker
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue