forked from orbit-oss/flask
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
|
||||
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`
|
||||
subclass and provides all of the attributes Werkzeug defines. This
|
||||
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
|
||||
difference that it keeps track on modifications.
|
||||
|
||||
This is a proxy. See :ref:`notes-on-proxies` for more information.
|
||||
|
||||
The following attributes are interesting:
|
||||
|
||||
.. 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
|
||||
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
|
||||
----------------------------
|
||||
|
|
@ -216,6 +222,8 @@ Useful Functions and Classes
|
|||
extensions that want to support multiple applications running side
|
||||
by side.
|
||||
|
||||
This is a proxy. See :ref:`notes-on-proxies` for more information.
|
||||
|
||||
.. autofunction:: url_for
|
||||
|
||||
.. function:: abort(code)
|
||||
|
|
@ -389,6 +397,8 @@ Signals
|
|||
in debug mode, where no exception handling happens. The exception
|
||||
itself is passed to the subscriber as `exception`.
|
||||
|
||||
.. currentmodule:: None
|
||||
|
||||
.. class:: flask.signals.Namespace
|
||||
|
||||
An alias for :class:`blinker.base.Namespace` if blinker is available,
|
||||
|
|
@ -404,3 +414,28 @@ Signals
|
|||
operations, including connecting.
|
||||
|
||||
.. _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.
|
||||
|
||||
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
|
||||
the documentation when subscribing to signals.
|
||||
|
||||
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.
|
||||
signal. When you subscribe to a signal, be sure to also provide a sender
|
||||
unless you really want to listen for signals of all applications. This is
|
||||
especially true if you are developing an extension.
|
||||
|
||||
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
|
||||
|
|
@ -57,19 +53,19 @@ to the template::
|
|||
from contextlib import contextmanager
|
||||
|
||||
@contextmanager
|
||||
def captured_templates():
|
||||
def captured_templates(app):
|
||||
recorded = []
|
||||
def record(template, context):
|
||||
recorded.append((template, context))
|
||||
template_rendered.connect(record)
|
||||
template_rendered.connect(record, app)
|
||||
try:
|
||||
yield recorded
|
||||
finally:
|
||||
template_rendered.disconnect(record)
|
||||
template_rendered.disconnect(record, app)
|
||||
|
||||
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('/')
|
||||
assert rv.status_code == 200
|
||||
assert len(templates) == 1
|
||||
|
|
@ -77,9 +73,23 @@ This can now easily be paired with a test client::
|
|||
assert template.name == 'index.html'
|
||||
assert len(context['items']) == 10
|
||||
|
||||
All the template rendering in the code, the `with` block wraps will now be
|
||||
recorded in the `templates` variable. Whenever a template is rendered,
|
||||
the template object as well as context is appended to it.
|
||||
All the template rendering in the code issued by the application `app`
|
||||
in the body of the `with` block will now be recorded in the `templates`
|
||||
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
|
||||
----------------
|
||||
|
|
@ -153,7 +163,7 @@ The following signals exist in Flask:
|
|||
context)
|
||||
|
||||
from flask import request_started
|
||||
request_started.connect(log_template_renders)
|
||||
request_started.connect(log_template_renders, app)
|
||||
|
||||
.. data:: flask.request_started
|
||||
:noindex:
|
||||
|
|
@ -169,7 +179,7 @@ The following signals exist in Flask:
|
|||
sender.logger.debug('Request context is set up')
|
||||
|
||||
from flask import request_started
|
||||
request_started.connect(log_request)
|
||||
request_started.connect(log_request, app)
|
||||
|
||||
.. data:: flask.request_finished
|
||||
:noindex:
|
||||
|
|
@ -184,7 +194,7 @@ The following signals exist in Flask:
|
|||
'Response: %s', response)
|
||||
|
||||
from flask import request_finished
|
||||
request_finished.connect(log_response)
|
||||
request_finished.connect(log_response, app)
|
||||
|
||||
.. data:: flask.got_request_exception
|
||||
:noindex:
|
||||
|
|
@ -200,6 +210,6 @@ The following signals exist in Flask:
|
|||
sender.logger.debug('Got exception during processing: %s', 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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue