.. _renderers_chapter:

Renderers
=========

In the :ref:`views_chapter` chapter, we said that a view callable must
return a :term:`Response` object.  We lied.  A :term:`renderer` is a service
that attempts to convert a non-Response return value of a function, class, or
instance that acts as a :term:`view callable` to a :term:`Response` object.

Overview
--------

A view needn't *always* return a Response object.  If a view happens to
return something which does not implement the Pyramid Response interface,
:app:`Pyramid` will attempt to use a :term:`renderer` to construct a
response.  For example:

.. code-block:: python
   :linenos:

   from pyramid.response import Response
   from pyramid.view import view_config

   def hello_world(request):
       return {'content':'Hello!'}

The above example returns a *dictionary* from the view callable.  A
dictionary does not implement the Pyramid response interface, so you might
believe that this example would fail.  However, since a ``renderer`` is
associated with the view callable through its :term:`view configuration` (in
this case, using a ``renderer`` argument passed to
:func:`pyramid.view.view_config`), if the view does *not* return a Response
object, the renderer will attempt to convert the result of the view to a
response on the developer's behalf.

Of course, if no renderer is associated with a view's configuration,
returning anything except an object which implements the Response interface
will result in an error.  And, if a renderer *is* used, whatever is returned
by the view must be compatible with the particular kind of renderer used, or
an error may occur during view invocation.

One exception exists: it is *always* OK to return a Response object, even
when a ``renderer`` is configured.  If a view callable returns a response
object from a view that is configured with a renderer, the renderer is
bypassed entirely.

Various types of renderers exist, including serialization renderers
and renderers which use templating systems.  See also
:ref:`views_which_use_a_renderer`.


.. index::
   single: renderer
   single: view renderer

.. _views_which_use_a_renderer:

Writing View Callables Which Use a Renderer
-------------------------------------------

As we've seen, view callables needn't always return a Response object.
Instead, they may return an arbitrary Python object, with the expectation
that a :term:`renderer` will convert that object into a response instance on
your behalf.  Some renderers use a templating system; other renderers use
object serialization techniques.

View configuration can vary the renderer associated with a view callable via
the ``renderer`` attribute.  For example, this call to
:meth:`pyramid.config.Configurator.add_view` associates the ``json`` renderer
with a view callable:

.. code-block:: python
   :linenos:

   config.add_view('myproject.views.my_view', renderer='json')

When this configuration is added to an application, the
``myproject.views.my_view`` view callable will now use a ``json`` renderer,
which renders view return values to a :term:`JSON` response serialization.

Other built-in renderers include renderers which use the :term:`Chameleon`
templating language to render a dictionary to a response.

If the :term:`view callable` associated with a :term:`view configuration`
returns a Response object directly (an object with the attributes ``status``,
``headerlist`` and ``app_iter``), any renderer associated with the view
configuration is ignored, and the response is passed back to :app:`Pyramid`
unmolested.  For example, if your view callable returns an instance of the
:class:`pyramid.httpexceptions.HTTPFound` class as a response, no renderer
will be employed.

.. code-block:: python
   :linenos:

   from pyramid.httpexceptions import HTTPFound

   def view(request):
       return HTTPFound(location='http://example.com') # any renderer avoided

Views which use a renderer can vary non-body response attributes (such as
headers and the HTTP status code) by attaching properties to the request.
See :ref:`response_request_attrs`.

Additional renderers can be added by developers to the system as necessary
(see :ref:`adding_and_overriding_renderers`).

.. index::
   single: renderers (built-in)
   single: built-in renderers

.. _built_in_renderers:

Built-In Renderers
------------------

Several built-in renderers exist in :app:`Pyramid`.  These renderers can be
used in the ``renderer`` attribute of view configurations.

.. index::
   pair: renderer; string

``string``: String Renderer
~~~~~~~~~~~~~~~~~~~~~~~~~~~

The ``string`` renderer is a renderer which renders a view callable result to
a string.  If a view callable returns a non-Response object, and the
``string`` renderer is associated in that view's configuration, the result
will be to run the object through the Python ``str`` function to generate a
string.  Note that if a Unicode object is returned by the view callable, it
is not ``str()`` -ified.

Here's an example of a view that returns a dictionary.  If the ``string``
renderer is specified in the configuration for this view, the view will
render the returned dictionary to the ``str()`` representation of the
dictionary:

.. code-block:: python
   :linenos:

   from pyramid.response import Response
   from pyramid.view import view_config

   @view_config(renderer='string')
   def hello_world(request):
       return {'content':'Hello!'}

The body of the response returned by such a view will be a string
representing the ``str()`` serialization of the return value:

.. code-block:: python
   :linenos:

   {'content': 'Hello!'}

Views which use the string renderer can vary non-body response attributes by
attaching properties to the request.  See :ref:`response_request_attrs`.

.. index::
   pair: renderer; JSON

``json``: JSON Renderer
~~~~~~~~~~~~~~~~~~~~~~~

The ``json`` renderer renders view callable results to :term:`JSON`.  It
passes the return value through the ``json.dumps`` standard library function,
and wraps the result in a response object.  It also sets the response
content-type to ``application/json``.

Here's an example of a view that returns a dictionary.  Since the ``json``
renderer is specified in the configuration for this view, the view will
render the returned dictionary to a JSON serialization:

.. code-block:: python
   :linenos:

   from pyramid.response import Response
   from pyramid.view import view_config

   @view_config(renderer='json')
   def hello_world(request):
       return {'content':'Hello!'}

The body of the response returned by such a view will be a string
representing the JSON serialization of the return value:

.. code-block:: python
   :linenos:

   '{"content": "Hello!"}'

The return value needn't be a dictionary, but the return value must contain
values serializable by :func:`json.dumps`.

You can configure a view to use the JSON renderer by naming ``json`` as the
``renderer`` argument of a view configuration, e.g. by using
:meth:`pyramid.config.Configurator.add_view`:

.. code-block:: python
   :linenos:

   config.add_view('myproject.views.hello_world', 
                    name='hello',
                    context='myproject.resources.Hello',
                    renderer='json')
    

Views which use the JSON renderer can vary non-body response attributes by
attaching properties to the request.  See :ref:`response_request_attrs`.

.. index::
   pair: renderer; chameleon

.. _chameleon_template_renderers:

``*.pt`` or ``*.txt``: Chameleon Template Renderers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Two built-in renderers exist for :term:`Chameleon` templates.

If the ``renderer`` attribute of a view configuration is an absolute path, a
relative path or :term:`asset specification` which has a final path element
with a filename extension of ``.pt``, the Chameleon ZPT renderer is used.
See :ref:`chameleon_zpt_templates` for more information about ZPT templates.

If the ``renderer`` attribute of a view configuration is an absolute path or
a :term:`asset specification` which has a final path element with a filename
extension of ``.txt``, the :term:`Chameleon` text renderer is used.  See
:ref:`chameleon_zpt_templates` for more information about Chameleon text
templates.

The behavior of these renderers is the same, except for the engine
used to render the template.

When a ``renderer`` attribute that names a template path or :term:`asset
specification` (e.g. ``myproject:templates/foo.pt`` or
``myproject:templates/foo.txt``) is used, the view must return a
:term:`Response` object or a Python *dictionary*.  If the view callable with
an associated template returns a Python dictionary, the named template will
be passed the dictionary as its keyword arguments, and the template renderer
implementation will return the resulting rendered template in a response to
the user.  If the view callable returns anything but a Response object or a
dictionary, an error will be raised.

Before passing keywords to the template, the keyword arguments derived from
the dictionary returned by the view are augmented.  The callable object --
whatever object was used to define the ``view`` -- will be automatically
inserted into the set of keyword arguments passed to the template as the
``view`` keyword.  If the view callable was a class, the ``view`` keyword
will be an instance of that class.  Also inserted into the keywords passed to
the template are ``renderer_name`` (the string used in the ``renderer``
attribute of the directive), ``renderer_info`` (an object containing
renderer-related information), ``context`` (the context resource of the view
used to render the template), and ``request`` (the request passed to the view
used to render the template).

Here's an example view configuration which uses a Chameleon ZPT renderer:

.. code-block:: python
   :linenos:

    # config is an instance of pyramid.config.Configurator

    config.add_view('myproject.views.hello_world',
                    name='hello',
                    context='myproject.resources.Hello',
                    renderer='myproject:templates/foo.pt')

Here's an example view configuration which uses a Chameleon text renderer:

.. code-block:: python
   :linenos:

    config.add_view('myproject.views.hello_world',
                    name='hello',
                    context='myproject.resources.Hello',
                    renderer='myproject:templates/foo.txt')

Views which use a Chameleon renderer can vary response attributes by
attaching properties to the request.  See :ref:`response_request_attrs`.

.. index::
   pair: renderer; mako

.. _mako_template_renderers:

``*.mak`` or ``*.mako``: Mako Template Renderer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The ``Mako`` template renderer renders views using a Mako template.  When
used, the view must return a Response object or a Python *dictionary*.  The
dictionary items will then be used in the global template space. If the view
callable returns anything but a Response object, or a dictionary, an error
will be raised.

When using a ``renderer`` argument to a :term:`view configuration` to specify
a Mako template, the value of the ``renderer`` may be a path relative to the
``mako.directories`` setting (e.g.  ``some/template.mak``) or, alternately,
it may be a :term:`asset specification`
(e.g. ``apackage:templates/sometemplate.mak``).  Mako templates may
internally inherit other Mako templates using a relative filename or a
:term:`asset specification` as desired.

Here's an example view configuration which uses a relative path:

.. code-block:: python
   :linenos:

    # config is an instance of pyramid.config.Configurator

    config.add_view('myproject.views.hello_world',
                    name='hello',
                    context='myproject.resources.Hello',
                    renderer='foo.mak')

It's important to note that in Mako's case, the 'relative' path name
``foo.mak`` above is not relative to the package, but is relative to the
directory (or directories) configured for Mako via the ``mako.directories``
configuration file setting.

The renderer can also be provided in :term:`asset specification`
format. Here's an example view configuration which uses one:

.. code-block:: python
   :linenos:

    config.add_view('myproject.views.hello_world',
                    name='hello',
                    context='myproject.resources.Hello',
                    renderer='mypackage:templates/foo.mak')

The above configuration will use the file named ``foo.mak`` in the
``templates`` directory of the ``mypackage`` package.

The ``Mako`` template renderer can take additional arguments beyond the
standard ``reload_templates`` setting, see the :ref:`environment_chapter` for
additional :ref:`mako_template_renderer_settings`.

.. index::
   single: response headers (from a renderer)
   single: renderer response headers

.. _response_request_attrs:

Varying Attributes of Rendered Responses
----------------------------------------

Before a response constructed by a :term:`renderer` is returned to
:app:`Pyramid`, several attributes of the request are examined which have the
potential to influence response behavior.

View callables that don't directly return a response should set these
attributes on the ``request`` object via ``setattr`` during their execution,
to influence associated response attributes.

``response_content_type``
  Defines the content-type of the resulting response,
  e.g. ``text/xml``.

``response_headerlist``
  A sequence of tuples describing cookie values that should be set in the
  response, e.g. ``[('Set-Cookie', 'abc=123'), ('X-My-Header', 'foo')]``.

``response_status``
  A WSGI-style status code (e.g. ``200 OK``) describing the status of the
  response.

``response_charset``
  The character set (e.g. ``UTF-8``) of the response.

``response_cache_for``
  A value in seconds which will influence ``Cache-Control`` and ``Expires``
  headers in the returned response.  The same can also be achieved by
  returning various values in the ``response_headerlist``, this is purely a
  convenience.

For example, if you need to change the response status from within a view
callable that uses a renderer, assign the ``response_status`` attribute to
the request before returning a result:

.. code-block:: python
   :linenos:

   from pyramid.view import view_config

   @view_config(name='gone', renderer='templates/gone.pt')
   def myview(request):
       request.response_status = '404 Not Found'
       return {'URL':request.URL}

For more information on attributes of the request, see the API
documentation in :ref:`request_module`.

.. index::
   single: renderer (adding)

.. _adding_and_overriding_renderers:

Adding and Overriding Renderers
-------------------------------

New templating systems and serializers can be associated with :app:`Pyramid`
renderer names.  To this end, configuration declarations can be made which
override an existing :term:`renderer factory`, and which add a new renderer
factory.

Renderers can be registered imperatively using the
:meth:`pyramid.config.Configurator.add_renderer` API.

.. note:: The tasks described in this section can also be performed via
   :term:`declarative configuration`.  See
   :ref:`zcml_adding_and_overriding_renderers`.

For example, to add a renderer which renders views which have a
``renderer`` attribute that is a path that ends in ``.jinja2``:

.. code-block:: python
   :linenos:

   config.add_renderer('.jinja2', 'mypackage.MyJinja2Renderer')

The first argument is the renderer name.  The second argument is a reference
to an implementation of a :term:`renderer factory` or a :term:`dotted Python
name` referring to such an object.

.. _adding_a_renderer:

Adding a New Renderer
~~~~~~~~~~~~~~~~~~~~~

You may add a new renderer by creating and registering a :term:`renderer
factory`.

A renderer factory implementation is typically a class with the
following interface:

.. code-block:: python
   :linenos:

   class RendererFactory:
       def __init__(self, info):
           """ Constructor: ``info`` will be an object having the
           the following attributes: ``name`` (the renderer name), ``package`` 
           (the package that was 'current' at the time the renderer was 
           registered), ``type`` (the renderer type name), ``registry`` 
           (the current application registry) and ``settings`` (the 
           deployment settings dictionary).
           """

       def __call__(self, value, system):
           """ Call a the renderer implementation with the value and
           the system value passed in as arguments and return the
           result (a string or unicode object).  The value is the
           return value of a view.  The system value is a dictionary
           containing available system values (e.g. ``view``,
           ``context``, and ``request``). """

The formal interface definition of the ``info`` object passed to a renderer
factory constructor is available as :class:`pyramid.interfaces.IRendererInfo`.

There are essentially two different kinds of renderer factories:

- A renderer factory which expects to accept a :term:`asset
  specification`, or an absolute path, as the ``name`` attribute of the
  ``info`` object fed to its constructor.  These renderer factories are
  registered with a ``name`` value that begins with a dot (``.``).  These
  types of renderer factories usually relate to a file on the filesystem,
  such as a template.

- A renderer factory which expects to accept a token that does not represent
  a filesystem path or a asset specification in the ``name``
  attribute of the ``info`` object fed to its constructor.  These renderer
  factories are registered with a ``name`` value that does not begin with a
  dot.  These renderer factories are typically object serializers.

.. sidebar:: Asset Specifications

   A asset specification is a colon-delimited identifier for a
   :term:`asset`.  The colon separates a Python :term:`package`
   name from a package subpath.  For example, the asset
   specification ``my.package:static/baz.css`` identifies the file named
   ``baz.css`` in the ``static`` subdirectory of the ``my.package`` Python
   :term:`package`.

Here's an example of the registration of a simple renderer factory via
:meth:`pyramid.config.Configurator.add_renderer`:

.. code-block:: python
   :linenos:

   # config is an instance of pyramid.config.Configurator

   config.add_renderer(name='amf', factory='my.package.MyAMFRenderer')

Adding the above code to your application startup configuration will
allow you to use the ``my.package.MyAMFRenderer`` renderer factory
implementation in view configurations. Your application can use this
renderer by specifying ``amf`` in the ``renderer`` attribute of a
:term:`view configuration`:

.. code-block:: python
   :linenos:

   from pyramid.view import view_config

   @view_config(renderer='amf')
   def myview(request):
       return {'Hello':'world'}

At startup time, when a :term:`view configuration` is encountered, which
has a ``name`` attribute that does not contain a dot, the full ``name``
value is used to construct a renderer from the associated renderer
factory.  In this case, the view configuration will create an instance
of an ``AMFRenderer`` for each view configuration which includes ``amf``
as its renderer value.  The ``name`` passed to the ``AMFRenderer``
constructor will always be ``amf``.

Here's an example of the registration of a more complicated renderer
factory, which expects to be passed a filesystem path:

.. code-block:: python
   :linenos:

   config.add_renderer(name='.jinja2', 
                       factory='my.package.MyJinja2Renderer')

Adding the above code to your application startup will allow you to use the
``my.package.MyJinja2Renderer`` renderer factory implementation in view
configurations by referring to any ``renderer`` which *ends in* ``.jinja`` in
the ``renderer`` attribute of a :term:`view configuration`:

.. code-block:: python
   :linenos:

   from pyramid.view import view_config

   @view_config(renderer='templates/mytemplate.jinja2')
   def myview(request):
       return {'Hello':'world'}

When a :term:`view configuration` is encountered at startup time, which
has a ``name`` attribute that does contain a dot, the value of the name
attribute is split on its final dot.  The second element of the split is
typically the filename extension.  This extension is used to look up a
renderer factory for the configured view.  Then the value of
``renderer`` is passed to the factory to create a renderer for the view.
In this case, the view configuration will create an instance of a
``Jinja2Renderer`` for each view configuration which includes anything
ending with ``.jinja2`` in its ``renderer`` value.  The ``name`` passed
to the ``Jinja2Renderer`` constructor will be the full value that was
set as ``renderer=`` in the view configuration.

See also :ref:`renderer_directive` and
:meth:`pyramid.config.Configurator.add_renderer`.

Overriding an Existing Renderer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You can associate more than one filename extension with the same existing
renderer implementation as necessary if you need to use a different file
extension for the same kinds of templates.  For example, to associate the
``.zpt`` extension with the Chameleon ZPT renderer factory, use the
:meth:`pyramid.config.Configurator.add_renderer` method:

.. code-block:: python
   :linenos:

   config.add_renderer('.zpt', 'pyramid.chameleon_zpt.renderer_factory')

After you do this, :app:`Pyramid` will treat templates ending in both the
``.pt`` and ``.zpt`` filename extensions as Chameleon ZPT templates.

To override the default mapping in which files with a ``.pt`` extension are
rendered via a Chameleon ZPT page template renderer, use a variation on the
following in your application's startup code:

.. code-block:: python
   :linenos:

   config.add_renderer('.pt', 'mypackage.pt_renderer')

After you do this, the :term:`renderer factory` in
``mypackage.pt_renderer`` will be used to render templates which end
in ``.pt``, replacing the default Chameleon ZPT renderer.

To associate a *default* renderer with *all* view configurations (even
ones which do not possess a ``renderer`` attribute), pass ``None`` as
the ``name`` attribute to the renderer tag:

.. code-block:: python
   :linenos:

   config.add_renderer(None, 'mypackage.json_renderer_factory')

