summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2010-07-26 00:26:10 +0000
committerChris McDonough <chrism@agendaless.com>2010-07-26 00:26:10 +0000
commit250c0218d0bd7dab6ea7e16c7051af71394f2a63 (patch)
treed57c38c27b72a483a3db9b1150d20553a93472d8 /docs
parent2eb64f7a8bc7830667c3cb924bb5c13be3859b38 (diff)
downloadpyramid-250c0218d0bd7dab6ea7e16c7051af71394f2a63.tar.gz
pyramid-250c0218d0bd7dab6ea7e16c7051af71394f2a63.tar.bz2
pyramid-250c0218d0bd7dab6ea7e16c7051af71394f2a63.zip
merge generic_rendering branch
Diffstat (limited to 'docs')
-rw-r--r--docs/api.rst1
-rw-r--r--docs/api/configuration.rst10
-rw-r--r--docs/api/renderers.rst13
-rw-r--r--docs/glossary.rst5
-rw-r--r--docs/narr/hooks.rst66
-rw-r--r--docs/narr/templates.rst236
6 files changed, 263 insertions, 68 deletions
diff --git a/docs/api.rst b/docs/api.rst
index a97c79fa9..3bdb323ca 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -19,6 +19,7 @@ documentation is organized alphabetically by module name.
api/interfaces
api/location
api/paster
+ api/renderers
api/router
api/scripting
api/security
diff --git a/docs/api/configuration.rst b/docs/api/configuration.rst
index 68e3b8724..f555b18f0 100644
--- a/docs/api/configuration.rst
+++ b/docs/api/configuration.rst
@@ -5,7 +5,7 @@
.. automodule:: repoze.bfg.configuration
- .. autoclass:: Configurator(registry=None, package=None, settings=None, root_factory=None, authentication_policy=None, authorization_policy=None, renderers=DEFAULT_RENDERERS, debug_logger=None, locale_negotiator=None, request_factory=None)
+ .. autoclass:: Configurator(registry=None, package=None, settings=None, root_factory=None, authentication_policy=None, authorization_policy=None, renderers=DEFAULT_RENDERERS, debug_logger=None, locale_negotiator=None, request_factory=None, renderer_globals_factory=None)
.. attribute:: registry
@@ -20,7 +20,9 @@
.. automethod:: unhook_zca()
- .. automethod:: setup_registry(settings=None, root_factory=None, authentication_policy=None, renderers=DEFAULT_RENDERERS, debug_logger=None)
+ .. automethod:: get_settings
+
+ .. automethod:: setup_registry(settings=None, root_factory=None, authentication_policy=None, renderers=DEFAULT_RENDERERS, debug_logger=None, locale_negotiator=None, request_factory=None, renderer_globals_factory=None)
.. automethod:: add_renderer(name, factory)
@@ -54,11 +56,13 @@
.. automethod:: set_request_factory
+ .. automethod:: set_renderer_globals_factory
+
.. automethod:: testing_securitypolicy
.. automethod:: testing_models
.. automethod:: testing_add_subscriber
- .. automethod:: testing_add_template
+ .. automethod:: testing_add_renderer
diff --git a/docs/api/renderers.rst b/docs/api/renderers.rst
new file mode 100644
index 000000000..775b8d8d8
--- /dev/null
+++ b/docs/api/renderers.rst
@@ -0,0 +1,13 @@
+.. _renderers_module:
+
+:mod:`repoze.bfg.renderers`
+---------------------------
+
+.. module:: repoze.bfg.renderers
+
+.. autofunction:: get_renderer
+
+.. autofunction:: render
+
+.. autofunction:: render_to_response
+
diff --git a/docs/glossary.rst b/docs/glossary.rst
index a1adec50b..ce0d57111 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -756,3 +756,8 @@ Glossary
cultural context. Often shortened to "l10" (because the word
"localization" is L, 10 letters, then N). See also:
:term:`Internationalization`.
+
+ renderer globals
+ Values injected as names into a renderer based on application
+ policy. See :ref:`adding_renderer_globals` for more
+ information.
diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst
index 0614b48fd..89f126b07 100644
--- a/docs/narr/hooks.rst
+++ b/docs/narr/hooks.rst
@@ -394,6 +394,72 @@ method:
config = Configurator()
config.set_request_factory(MyRequestFactory)
+.. _adding_renderer_globals:
+
+Adding Renderer Globals
+-----------------------
+
+Whenever :mod:`repoze.bfg` handles a request to perform a rendering
+(after a view with a ``renderer=`` configuration attribute is invoked,
+or when the any of the methods beginning with ``render`` within the
+:mod:`repoze.bfg.renderers` module are called, *renderer globals* can
+be injected into the *system* values sent to the renderer. By
+default, no renderer globals are injected, and the "bare" system
+values (such as ``request``, ``context``, and ``renderer_name``) are
+the only values present in the system dictionary passed to every
+renderer.
+
+A callback that :mod:`repoze.bfg` will call every time a renderer is
+invoked can be added by passing a ``renderer_globals_factory``
+argument to the constructor of the :term:`configurator`.
+
+.. code-block:: python
+ :linenos:
+
+ def globals_factory(system):
+ return {'a':1}
+
+ config = Configurator(renderer_globals_factory=globals_factory)
+
+Such a callback must accept a single positional argument (notionally
+named ``system``) which will contain the original system values. It
+must return a dictionary of values that will be merged into the system
+dictionary.
+
+A renderer globals factory can alternately be registered via ZCML as a
+through the use of the ZCML ``utility`` directive. In the below, we
+assume a ``globals_factory`` function lives in a package named
+``mypackage.mymodule``.
+
+.. code-block:: xml
+ :linenos:
+
+ <utility
+ component="mypackage.mymodule.renderer_globals_factory"
+ provides="repoze.bfg.interfaces.IRendererGlobalsFactory"
+ />
+
+Lastly, if you're doing imperative configuration, and you'd rather do
+it after you've already constructed a :term:`configurator` it can also
+be registered via the
+:meth:`repoze.bfg.configuration.Configurator.set_renderer_globals_factory`
+method:
+
+.. code-block:: python
+ :linenos:
+
+ from repoze.bfg.configuration import Configurator
+ from repoze.bfg.request import Request
+
+.. code-block:: python
+ :linenos:
+
+ def globals_factory(system):
+ return {'a':1}
+
+ config = Configurator()
+ config.set_renderer_globals_factory(globals_factory)
+
.. _registering_configuration_decorators:
Registering Configuration Decorators
diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst
index e289df1f9..dce0733b6 100644
--- a/docs/narr/templates.rst
+++ b/docs/narr/templates.rst
@@ -31,46 +31,109 @@ The most straightforward way to use a template within
given templating engine to do so.
:mod:`repoze.bfg` provides various APIs that allow you to render
-:term:`Chameleon` templates directly from within a view callable. For
-example, if there is a :term:`Chameleon` ZPT template named ``foo.pt``
-in a directory in your application named ``templates``, you can render
-the template from within the body of a view callable like so:
+templates directly from within a view callable. For example, if there
+is a :term:`Chameleon` ZPT template named ``foo.pt`` in a directory in
+your application named ``templates``, you can render the template from
+within the body of a view callable like so:
.. code-block:: python
:linenos:
- from repoze.bfg.chameleon_zpt import render_template_to_response
+ from repoze.bfg.renderers import render_to_response
def sample_view(request):
- return render_template_to_response('templates/foo.pt', foo=1, bar=2)
+ return render_to_response('templates/foo.pt', foo=1, bar=2,
+ request=request)
+
+.. warning:: Earlier iterations of this documentation
+.. (pre-version-1.3) encouraged the application developer to use
+ ZPT-specific APIs such as
+ :func:`repoze.bfg.chameleon_zpt.render_template_to_response`,
+ :func:`repoze.bfg.chameleon_zpt.render_template_to_iterable`, and
+ :func:`repoze.bfg.chameleon_zpt.render_template` to render
+ templates directly. This style of rendering still works, but at
+ least for purposes of this documentation, those functions are
+ deprecated. Application developers are encouraged instead to use
+ the functions available in the :mod:`repoze.bfg.renderers` module
+ to perform rendering tasks. This set of functions works to render
+ templates for all renderer extensions registered with
+ :mod:`repoze.bfg`.
The ``sample_view`` :term:`view callable` above returns a
:term:`response` object which contains the body of the
-``template/foo.pt`` template. The template author will have the names
+``templates/foo.pt`` template. In this case, the ``templates``
+directory should live in the same directory as the module containing
+the ``sample_view`` function. The template author will have the names
``foo`` and ``bar`` available as top-level names for replacement or
comparison purposes.
+In the example above, the path ``templates/foo.pt`` is relative to the
+directory in which the file which defines the view configuration
+lives. In this case, this is the directory containing the file that
+defines the ``sample_view`` function. Although a renderer path is
+usually just a simple relative pathname, a path named as a renderer
+can be absolute, starting with a slash on UNIX or a drive letter
+prefix on Windows.
+
+The path can alternately be a :term:`resource specification` in the
+form ``some.dotted.package_name:relative/path``, making it possible to
+address template resources which live in another package. For
+example:
+
+.. code-block:: python
+ :linenos:
+
+ from repoze.bfg.renderers import render_to_response
+
+ def sample_view(request):
+ return render_to_response('mypackage:templates/foo.pt', foo=1, bar=2,
+ request=request)
+
+A resource specification points at a file within a Python *package*.
+In this case, it points at a file named ``foo.pt`` within the
+``templates`` directory of the ``mypackage`` package. Using a
+resource specification instead of a relative template name is usually
+a good idea, because calls to ``render_to_response`` using resource
+specifications will continue to work properly if you move the code
+containing them around.
+
+In the examples above we pass in a keyword argument named ``request``
+representing the current :mod:`repoze.bfg` request. Passing a request
+keyword argument will cause the ``render_to_response`` function to
+supply the renderer with more correct system values (see
+:ref:`renderer_system_values`), because most of the information
+required to compose proper system values is present in the request.
+If you care about the correct system values being provided to the
+renderer being called (in particular, if your template relies on the
+name ``request`` or ``context``, or if you've configured special
+:term:`renderer globals` make sure to pass ``request`` as a keyword
+argument in every call to to a ``repoze.bfg.renderers.render_*``
+function.
+
Every view must return a :term:`response` object (except for views
-which use a :term:`renderer`, which we'll see shortly). The
-:func:`repoze.bfg.chameleon_zpt.render_template_to_response` function
-is a shortcut function that actually returns a response object, but
-not all template APIs know about responses. When you use a template
-API that is "response-ignorant" you can also easily render a template
-to a string, and construct your own response object as necessary with
-the string as the body.
-
-For example, the :func:`repoze.bfg.chameleon_zpt.render_template` API
-returns a string. We can manufacture a :term:`response` object
-directly, and use that string as the body of the response:
+which use a :term:`renderer` named via view configuration, which we'll
+see shortly). The :func:`repoze.bfg.renders.render_to_response`
+function is a shortcut function that actually returns a response
+object.
+
+Obviously not all APIs you might call to get respnonse data will
+return a response object. If you call a "response-ignorant" API that
+returns information you'd like to use as a response (such as when you
+render a template to a string), you must construct your own response
+object as necessary with the string as the body. For example, the
+:func:`repoze.bfg.renderers.render` API returns a string. We can
+manufacture a :term:`response` object directly, and use that string as
+the body of the response:
.. code-block:: python
:linenos:
- from repoze.bfg.chameleon_zpt import render_template
+ from repoze.bfg.renderers import render
from webob import Response
def sample_view(request):
- result = render_template('templates/foo.pt', foo=1, bar=2)
+ result = render('mypackage:templates/foo.pt', foo=1, bar=2,
+ request=request)
response = Response(result)
return response
@@ -83,7 +146,7 @@ functions into your views module, use those APIs to generate a string,
then return that string as the body of a :term:`WebOb`
:term:`Response` object.
-For example, here's an example of using `Mako
+For example, here's an example of using raw `Mako
<http://www.makotemplates.org/>`_ from within a :mod:`repoze.bfg`
:term:`view`:
@@ -100,6 +163,13 @@ For example, here's an example of using `Mako
response = Response(result)
return response
+You probably wouldn't use this particular snippet in a project,
+because it's easier to use the Mako renderer bindings which already
+exist for :mod:`repoze.bfg` named ``repoze.bfg.mako`` (available from
+`PyPI <http://pypi.python.org/pypi/repoze.bfg.mako>`_). But if your
+favorite templating system is not supported as a renderer extension
+for BFG, you can create your own simple conmbination as shown above.
+
.. note::
If you use third-party templating languages without cooperating BFG
@@ -121,29 +191,31 @@ may set attributes on the response that influence these values.
Here's an example of changing the content-type and status of the
response object returned by
-:func:`repoze.bfg.chameleon_zpt.render_template_to_response`:
+:func:`repoze.bfg.renderers.render_to_response`:
.. code-block:: python
:linenos:
- from repoze.bfg.chameleon_zpt import render_template_to_response
+ from repoze.bfg.renderers.render_to_response
def sample_view(request):
- response = render_template_to_response('templates/foo.pt', foo=1, bar=2)
+ response = render_to_response('templates/foo.pt', foo=1, bar=2,
+ request=request)
response.content_type = 'text/plain'
response.status_int = 204
return response
-Here's an example of manufacturing a response object using the result of
-:func:`repoze.bfg.chameleon_zpt.render_template` (a string):
+Here's an example of manufacturing a response object using the result
+of :func:`repoze.bfg.renderers.render` (a string):
.. code-block:: python
:linenos:
- from repoze.bfg.chameleon_zpt import render_template
+ from repoze.bfg.renderers import render
from webob import Response
def sample_view(request):
- result = render_template('templates/foo.pt', foo=1, bar=2)
+ result = render('mypackage:templates/foo.pt', foo=1, bar=2,
+ request=request)
response = Response(result)
response.content_type = 'text/plain'
return response
@@ -153,22 +225,50 @@ Here's an example of manufacturing a response object using the result of
single: template renderers
single: renderer (template)
+
+.. _renderer_system_values:
+
+System Values Used During Rendering
+-----------------------------------
+
+When a template is rendered using
+:func:`repoze.bfg.render_to_response` or :func:`repoze.bfg.render`,
+the renderer representing the template will be provided with a number
+of *system* values. These values are provided in a dictionary to the
+renderer and include:
+
+``context``
+ The current :mod:`repoze.bfg` context if ``request`` was provided as
+ a keyword argument or ``None``.
+
+``request``
+ The request provided as a keyword argument.
+
+``renderer_name``
+ The renderer name used to perform the rendering,
+ e.g. ``mypackage:templates/foo.pt``.
+
+What any particular renderer does with them is up to the renderer
+itself, but most renderers, including al Chameleon renderers, make
+these names available as top-level template variables.
+
.. _templates_used_as_renderers:
-Templates Used as Renderers
----------------------------
+Templates Used as Renderers via Configuration
+---------------------------------------------
-Instead of using templating system APIs within the body of a view
-function directly to render a specific template, you may associate a
-template written in a supported templating language with a view
-indirectly by specifying it as a :term:`renderer`.
+Instead of using the :func:`repoze.bfg.renderers.render_to_response`
+API within the body of a view function directly to render a specific
+template to a response, you may associate a template written in a
+supported templating language with a view indirectly by specifying it
+as a :term:`renderer` in *view configuration*.
-To use a renderer, specify a template :term:`resource specification`
-as the ``renderer`` argument or attribute to the :term:`view
-configuration` of a :term:`view callable`. Then return a *dictionary*
-from that view callable. The dictionary items returned by the view
-callable will be made available to the renderer template as top-level
-names.
+To use a renderer via view configuration, specify a template
+:term:`resource specification` as the ``renderer`` argument or
+attribute to the :term:`view configuration` of a :term:`view
+callable`. Then return a *dictionary* from that view callable. The
+dictionary items returned by the view callable will be made available
+to the renderer template as top-level names.
The association of a template as a renderer for a :term:`view
configuration` makes it possible to replace code within a :term:`view
@@ -187,6 +287,18 @@ template renderer:
def my_view(request):
return {'foo':1, 'bar':2}
+.. note:: It is not necessary to supply the ``request`` value as a key
+ in the dictionary result returned from a renderer-configured view
+ callable in order to ensure that the "most correct" system values
+ are supplied to the renderer as it is when you use
+ :func:`repoze.bfg.renderers.render` or
+ :func:`repoze.bfg.renderers.render_to_response`. This is handled
+ automatically.
+
+Similar renderer configuration can be done imperatively and via
+:term:`ZCML`. See :ref:`views_which_use_a_renderer`. See also
+:ref:`built_in_renderers`.
+
The ``renderer`` argument to the ``@bfg_view`` configuration decorator
shown above is the template *path*. In the example above, the path
``templates/foo.pt`` is *relative*. Relative to what, you ask?
@@ -201,13 +313,6 @@ a :term:`resource specification` in the form
``some.dotted.package_name:relative/path``, making it possible to
address template resources which live in another package.
-When a template :term:`renderer` is used to render the result of a
-view callable, several names are passed into the template as top-level
-names by default, including ``context`` and ``request``. Similar
-renderer configuration can be done imperatively and via :term:`ZCML`.
-See :ref:`views_which_use_a_renderer`. See also
-:ref:`built_in_renderers`.
-
Not just any template from any arbitrary templating system may be used
as a renderer. Bindings must exist specifically for :mod:`repoze.bfg`
to use a templating language template as a renderer. Currently,
@@ -217,17 +322,18 @@ discussion of their details. :mod:`repoze.bfg` also supports the use
of :term:`Jinja2` templates as renderers. See
:ref:`available_template_system_bindings`.
-.. sidebar:: Why Use A Renderer
-
- Using a renderer is usually a better way to render templates than
- using any templating API directly from within a :term:`view
- callable` because it makes the view callable more unit-testable.
- Views which use templating APIs directly must return a
- :term:`Response` object. Making testing assertions about response
- objects is typically an indirect process, because it means that
- your test code often needs to somehow parse information
- out of the response body (often HTML). View callables which use
- renderers typically return a dictionary, and making assertions
+.. sidebar:: Why Use A Renderer via View Configuration
+
+ Using a renderer in view configuration is usually a better way to
+ render templates than using any rendering API directly from within
+ a :term:`view callable` because it makes the view callable more
+ unit-testable. Views which use templating or rendering APIs
+ directly must return a :term:`Response` object. Making testing
+ assertions about response objects is typically an indirect process,
+ because it means that your test code often needs to somehow parse
+ information out of the response body (often HTML). View callables
+ which are configured with renderers externally via view
+ configuration typically return a dictionary, and making assertions
about the information is almost always more direct than needing to
parse HTML. Specifying a renderer from within :term:`ZCML` (as
opposed to imperatively or via a ``bfg_view`` decorator, or using a
@@ -244,6 +350,11 @@ status attributes, you must set attributes on the *request* object
within the view before returning the dictionary. See
:ref:`response_request_attrs` for more information.
+The same set of system values are provided to templates rendered via a
+rendere view configuration as those provided to templates rendered
+imperatively. See :ref:`renderer_system_values`.
+
+
.. index::
single: Chameleon ZPT templates
single: ZPT templates (Chameleon)
@@ -285,10 +396,6 @@ the template as a :term:`renderer` like so:
def my_view(request):
return {'foo':1, 'bar':2}
-If you'd rather use templates directly within a view callable (without
-the indirection of using a renderer), see :ref:`chameleon_zpt_module`
-for the API description.
-
See also :ref:`built_in_renderers` for more general information about
renderers, including Chameleon ZPT renderers.
@@ -323,9 +430,8 @@ Here's what a simple :term:`Chameleon` ZPT template used under
Note the use of :term:`Genshi` -style ``${replacements}`` above. This
is one of the ways that :term:`Chameleon` ZPT differs from standard
ZPT. The above template expects to find a ``project`` key in the set
-of keywords passed in to it via
-:func:`repoze.bfg.chameleon_zpt.render_template` or
-:func:`repoze.bfg.render_template_to_response`. Typical ZPT
+of keywords passed in to it via :func:`repoze.bfg.renderers.render` or
+:func:`repoze.bfg.renderers.render_to_response`. Typical ZPT
attribute-based syntax (e.g. ``tal:content`` and ``tal:replace``) also
works in these templates.