1.. _renderers_chapter: 2 3Renderers 4========= 5 6A view callable needn't *always* return a :term:`Response` object. If a view 7happens to return something which does not implement the Pyramid Response 8interface, :app:`Pyramid` will attempt to use a :term:`renderer` to construct a 9response. For example: 10 11.. code-block:: python 12 :linenos: 13 14 from pyramid.view import view_config 15 16 @view_config(renderer='json') 17 def hello_world(request): 18 return {'content':'Hello!'} 19 20The above example returns a *dictionary* from the view callable. A dictionary 21does not implement the Pyramid response interface, so you might believe that 22this example would fail. However, since a ``renderer`` is associated with the 23view callable through its :term:`view configuration` (in this case, using a 24``renderer`` argument passed to :func:`~pyramid.view.view_config`), if the view 25does *not* return a Response object, the renderer will attempt to convert the 26result of the view to a response on the developer's behalf. 27 28Of course, if no renderer is associated with a view's configuration, returning 29anything except an object which implements the Response interface will result 30in an error. And, if a renderer *is* used, whatever is returned by the view 31must be compatible with the particular kind of renderer used, or an error may 32occur during view invocation. 33 34One exception exists: it is *always* OK to return a Response object, even when 35a ``renderer`` is configured. In such cases, the renderer is bypassed 36entirely. 37 38Various types of renderers exist, including serialization renderers and 39renderers which use templating systems. 40 41.. index:: 42 single: renderer 43 single: view renderer 44 45.. _views_which_use_a_renderer: 46 47Writing View Callables Which Use a Renderer 48------------------------------------------- 49 50As we've seen, a view callable needn't always return a Response object. 51Instead, it may return an arbitrary Python object, with the expectation that a 52:term:`renderer` will convert that object into a response instance on your 53behalf. Some renderers use a templating system, while other renderers use 54object serialization techniques. In practice, renderers obtain application 55data values from Python dictionaries so, in practice, view callables which use 56renderers return Python dictionaries. 57 58View callables can :ref:`explicitly call <example_render_to_response_call>` 59renderers, but typically don't. Instead view configuration declares the 60renderer used to render a view callable's results. This is done with the 61``renderer`` attribute. For example, this call to 62:meth:`~pyramid.config.Configurator.add_view` associates the ``json`` renderer 63with a view callable: 64 65.. code-block:: python 66 67 config.add_view('myproject.views.my_view', renderer='json') 68 69When this configuration is added to an application, the 70``myproject.views.my_view`` view callable will now use a ``json`` renderer, 71which renders view return values to a :term:`JSON` response serialization. 72 73Pyramid defines several :ref:`built_in_renderers`, and additional renderers can 74be added by developers to the system as necessary. See 75:ref:`adding_and_overriding_renderers`. 76 77Views which use a renderer and return a non-Response value can vary non-body 78response attributes (such as headers and the HTTP status code) by attaching a 79property to the ``request.response`` attribute. See 80:ref:`request_response_attr`. 81 82As already mentioned, if the :term:`view callable` associated with a 83:term:`view configuration` returns a Response object (or its instance), any 84renderer associated with the view configuration is ignored, and the response is 85passed back to :app:`Pyramid` unchanged. For example: 86 87.. code-block:: python 88 :linenos: 89 90 from pyramid.response import Response 91 from pyramid.view import view_config 92 93 @view_config(renderer='json') 94 def view(request): 95 return Response('OK') # json renderer avoided 96 97Likewise for an :term:`HTTP exception` response: 98 99.. code-block:: python 100 :linenos: 101 102 from pyramid.httpexceptions import HTTPFound 103 from pyramid.view import view_config 104 105 @view_config(renderer='json') 106 def view(request): 107 return HTTPFound(location='http://example.com') # json renderer avoided 108 109You can of course also return the ``request.response`` attribute instead to 110avoid rendering: 111 112.. code-block:: python 113 :linenos: 114 115 from pyramid.view import view_config 116 117 @view_config(renderer='json') 118 def view(request): 119 request.response.body = 'OK' 120 return request.response # json renderer avoided 121 122.. index:: 123 single: renderers (built-in) 124 single: built-in renderers 125 126.. _built_in_renderers: 127 128Built-in Renderers 129------------------ 130 131Several built-in renderers exist in :app:`Pyramid`. These renderers can be 132used in the ``renderer`` attribute of view configurations. 133 134.. note:: 135 136 Bindings for officially supported templating languages can be found at 137 :ref:`available_template_system_bindings`. 138 139.. index:: 140 pair: renderer; string 141 142``string``: String Renderer 143~~~~~~~~~~~~~~~~~~~~~~~~~~~ 144 145The ``string`` renderer renders a view callable result to a string. If a view 146callable returns a non-Response object, and the ``string`` renderer is 147associated in that view's configuration, the result will be to run the object 148through the Python ``str`` function to generate a string. Note that if a 149Unicode object is returned by the view callable, it is not ``str()``-ified. 150 151Here's an example of a view that returns a dictionary. If the ``string`` 152renderer is specified in the configuration for this view, the view will render 153the returned dictionary to the ``str()`` representation of the dictionary: 154 155.. code-block:: python 156 :linenos: 157 158 from pyramid.view import view_config 159 160 @view_config(renderer='string') 161 def hello_world(request): 162 return {'content':'Hello!'} 163 164The body of the response returned by such a view will be a string representing 165the ``str()`` serialization of the return value: 166 167.. code-block:: python 168 169 {'content': 'Hello!'} 170 171Views which use the string renderer can vary non-body response attributes by 172using the API of the ``request.response`` attribute. See 173:ref:`request_response_attr`. 174 175.. index:: 176 pair: renderer; JSON 177 178.. _json_renderer: 179 180JSON Renderer 181~~~~~~~~~~~~~ 182 183The ``json`` renderer renders view callable results to :term:`JSON`. By 184default, it passes the return value through the ``json.dumps`` standard library 185function, and wraps the result in a response object. It also sets the response 186content-type to ``application/json``. 187 188Here's an example of a view that returns a dictionary. Since the ``json`` 189renderer is specified in the configuration for this view, the view will render 190the returned dictionary to a JSON serialization: 191 192.. code-block:: python 193 :linenos: 194 195 from pyramid.view import view_config 196 197 @view_config(renderer='json') 198 def hello_world(request): 199 return {'content':'Hello!'} 200 201The body of the response returned by such a view will be a string representing 202the JSON serialization of the return value: 203 204.. code-block:: python 205 206 {"content": "Hello!"} 207 208The return value needn't be a dictionary, but the return value must contain 209values serializable by the configured serializer (by default ``json.dumps``). 210 211You can configure a view to use the JSON renderer by naming ``json`` as the 212``renderer`` argument of a view configuration, e.g., by using 213:meth:`~pyramid.config.Configurator.add_view`: 214 215.. code-block:: python 216 :linenos: 217 218 config.add_view('myproject.views.hello_world', 219 name='hello', 220 context='myproject.resources.Hello', 221 renderer='json') 222 223Views which use the JSON renderer can vary non-body response attributes by 224using the API of the ``request.response`` attribute. See 225:ref:`request_response_attr`. 226 227.. _json_serializing_custom_objects: 228 229Serializing Custom Objects 230++++++++++++++++++++++++++ 231 232Some objects are not, by default, JSON-serializable (such as datetimes and 233other arbitrary Python objects). You can, however, register code that makes 234non-serializable objects serializable in two ways: 235 236- Define a ``__json__`` method on objects in your application. 237 238- For objects you don't "own", you can register a JSON renderer that knows 239 about an *adapter* for that kind of object. 240 241Using a Custom ``__json__`` Method 242********************************** 243 244Custom objects can be made easily JSON-serializable in Pyramid by defining a 245``__json__`` method on the object's class. This method should return values 246natively JSON-serializable (such as ints, lists, dictionaries, strings, and so 247forth). It should accept a single additional argument, ``request``, which will 248be the active request object at render time. 249 250.. code-block:: python 251 :linenos: 252 253 from pyramid.view import view_config 254 255 class MyObject(object): 256 def __init__(self, x): 257 self.x = x 258 259 def __json__(self, request): 260 return {'x':self.x} 261 262 @view_config(renderer='json') 263 def objects(request): 264 return [MyObject(1), MyObject(2)] 265 266 # the JSON value returned by ``objects`` will be: 267 # [{"x": 1}, {"x": 2}] 268 269Using the ``add_adapter`` Method of a Custom JSON Renderer 270********************************************************** 271 272If you aren't the author of the objects being serialized, it won't be possible 273(or at least not reasonable) to add a custom ``__json__`` method to their 274classes in order to influence serialization. If the object passed to the 275renderer is not a serializable type and has no ``__json__`` method, usually a 276:exc:`TypeError` will be raised during serialization. You can change this 277behavior by creating a custom JSON renderer and adding adapters to handle 278custom types. The renderer will attempt to adapt non-serializable objects using 279the registered adapters. A short example follows: 280 281.. code-block:: python 282 :linenos: 283 284 from pyramid.renderers import JSON 285 286 if __name__ == '__main__': 287 config = Configurator() 288 json_renderer = JSON() 289 def datetime_adapter(obj, request): 290 return obj.isoformat() 291 json_renderer.add_adapter(datetime.datetime, datetime_adapter) 292 config.add_renderer('json', json_renderer) 293 294The ``add_adapter`` method should accept two arguments: the *class* of the 295object that you want this adapter to run for (in the example above, 296``datetime.datetime``), and the adapter itself. 297 298The adapter should be a callable. It should accept two arguments: the object 299needing to be serialized and ``request``, which will be the current request 300object at render time. The adapter should raise a :exc:`TypeError` if it can't 301determine what to do with the object. 302 303See :class:`pyramid.renderers.JSON` and :ref:`adding_and_overriding_renderers` 304for more information. 305 306.. versionadded:: 1.4 307 Serializing custom objects. 308 309.. index:: 310 pair: renderer; JSONP 311 312.. _jsonp_renderer: 313 314JSONP Renderer 315~~~~~~~~~~~~~~ 316 317.. versionadded:: 1.1 318 319:class:`pyramid.renderers.JSONP` is a `JSONP 320<https://en.wikipedia.org/wiki/JSONP>`_ renderer factory helper which implements 321a hybrid JSON/JSONP renderer. JSONP is useful for making cross-domain AJAX 322requests. 323 324Unlike other renderers, a JSONP renderer needs to be configured at startup time 325"by hand". Configure a JSONP renderer using the 326:meth:`pyramid.config.Configurator.add_renderer` method: 327 328.. code-block:: python 329 330 from pyramid.config import Configurator 331 from pyramid.renderers import JSONP 332 333 config = Configurator() 334 config.add_renderer('jsonp', JSONP(param_name='callback')) 335 336Once this renderer is registered via 337:meth:`~pyramid.config.Configurator.add_renderer` as above, you can use 338``jsonp`` as the ``renderer=`` parameter to ``@view_config`` or 339:meth:`pyramid.config.Configurator.add_view`: 340 341.. code-block:: python 342 343 from pyramid.view import view_config 344 345 @view_config(renderer='jsonp') 346 def myview(request): 347 return {'greeting':'Hello world'} 348 349When a view is called that uses a JSONP renderer: 350 351- If there is a parameter in the request's HTTP query string (aka 352 ``request.GET``) that matches the ``param_name`` of the registered JSONP 353 renderer (by default, ``callback``), the renderer will return a JSONP 354 response. 355 356- If there is no callback parameter in the request's query string, the renderer 357 will return a "plain" JSON response. 358 359Javscript library AJAX functionality will help you make JSONP requests. 360For example, JQuery has a `getJSON function 361<http://api.jquery.com/jQuery.getJSON/>`_, and has equivalent (but more 362complicated) functionality in its `ajax function 363<http://api.jquery.com/jQuery.ajax/>`_. 364 365For example (JavaScript): 366 367.. code-block:: javascript 368 369 var api_url = 'http://api.geonames.org/timezoneJSON' + 370 '?lat=38.301733840000004' + 371 '&lng=-77.45869621' + 372 '&username=fred' + 373 '&callback=?'; 374 jqhxr = $.getJSON(api_url); 375 376The string ``callback=?`` above in the ``url`` param to the JQuery ``getJSON`` 377function indicates to jQuery that the query should be made as a JSONP request; 378the ``callback`` parameter will be automatically filled in for you and used. 379 380The same custom-object serialization scheme defined used for a "normal" JSON 381renderer in :ref:`json_serializing_custom_objects` can be used when passing 382values to a JSONP renderer too. 383 384.. index:: 385 single: response headers (from a renderer) 386 single: renderer response headers 387 388.. _request_response_attr: 389 390Varying Attributes of Rendered Responses 391---------------------------------------- 392 393Before a response constructed by a :term:`renderer` is returned to 394:app:`Pyramid`, several attributes of the request are examined which have the 395potential to influence response behavior. 396 397View callables that don't directly return a response should use the API of the 398:class:`pyramid.response.Response` attribute, available as ``request.response`` 399during their execution, to influence associated response behavior. 400 401For example, if you need to change the response status from within a view 402callable that uses a renderer, assign the ``status`` attribute to the 403``response`` attribute of the request before returning a result: 404 405.. code-block:: python 406 :linenos: 407 408 from pyramid.view import view_config 409 410 @view_config(name='gone', renderer='templates/gone.pt') 411 def myview(request): 412 request.response.status = '404 Not Found' 413 return {'URL':request.URL} 414 415Note that mutations of ``request.response`` in views which return a Response 416object directly will have no effect unless the response object returned *is* 417``request.response``. For example, the following example calls 418``request.response.set_cookie``, but this call will have no effect because a 419different Response object is returned. 420 421.. code-block:: python 422 :linenos: 423 424 from pyramid.response import Response 425 426 def view(request): 427 request.response.set_cookie('abc', '123') # this has no effect 428 return Response('OK') # because we're returning a different response 429 430If you mutate ``request.response`` and you'd like the mutations to have an 431effect, you must return ``request.response``: 432 433.. code-block:: python 434 :linenos: 435 436 def view(request): 437 request.response.set_cookie('abc', '123') 438 return request.response 439 440For more information on attributes of the request, see the API documentation in 441:ref:`request_module`. For more information on the API of 442``request.response``, see :attr:`pyramid.request.Request.response`. 443 444.. _adding_and_overriding_renderers: 445 446Adding and Changing Renderers 447----------------------------- 448 449New templating systems and serializers can be associated with :app:`Pyramid` 450renderer names. To this end, configuration declarations can be made which 451change an existing :term:`renderer factory`, and which add a new renderer 452factory. 453 454Renderers can be registered imperatively using the 455:meth:`pyramid.config.Configurator.add_renderer` API. 456 457For example, to add a renderer which renders views which have a 458``renderer`` attribute that is a path that ends in ``.jinja2``: 459 460.. code-block:: python 461 462 config.add_renderer('.jinja2', 'mypackage.MyJinja2Renderer') 463 464The first argument is the renderer name. The second argument is a reference 465to an implementation of a :term:`renderer factory` or a :term:`dotted Python 466name` referring to such an object. 467 468.. index:: 469 pair: renderer; adding 470 471.. _adding_a_renderer: 472 473Adding a New Renderer 474~~~~~~~~~~~~~~~~~~~~~ 475 476You may add a new renderer by creating and registering a :term:`renderer 477factory`. 478 479A renderer factory implementation should conform to the 480:class:`pyramid.interfaces.IRendererFactory` interface. It should be capable of 481creating an object that conforms to the :class:`pyramid.interfaces.IRenderer` 482interface. A typical class that follows this setup is as follows: 483 484.. code-block:: python 485 :linenos: 486 487 class RendererFactory: 488 def __init__(self, info): 489 """ Constructor: info will be an object having the 490 following attributes: name (the renderer name), package 491 (the package that was 'current' at the time the 492 renderer was registered), type (the renderer type 493 name), registry (the current application registry) and 494 settings (the deployment settings dictionary). """ 495 496 def __call__(self, value, system): 497 """ Call the renderer implementation with the value 498 and the system value passed in as arguments and return 499 the result (a string or unicode object). The value is 500 the return value of a view. The system value is a 501 dictionary containing available system values 502 (e.g., view, context, and request). """ 503 504The formal interface definition of the ``info`` object passed to a renderer 505factory constructor is available as :class:`pyramid.interfaces.IRendererInfo`. 506 507There are essentially two different kinds of renderer factories: 508 509- A renderer factory which expects to accept an :term:`asset specification`, or 510 an absolute path, as the ``name`` attribute of the ``info`` object fed to its 511 constructor. These renderer factories are registered with a ``name`` value 512 that begins with a dot (``.``). These types of renderer factories usually 513 relate to a file on the filesystem, such as a template. 514 515- A renderer factory which expects to accept a token that does not represent a 516 filesystem path or an asset specification in the ``name`` attribute of the 517 ``info`` object fed to its constructor. These renderer factories are 518 registered with a ``name`` value that does not begin with a dot. These 519 renderer factories are typically object serializers. 520 521.. sidebar:: Asset Specifications 522 523 An asset specification is a colon-delimited identifier for an :term:`asset`. 524 The colon separates a Python :term:`package` name from a package subpath. 525 For example, the asset specification ``my.package:static/baz.css`` 526 identifies the file named ``baz.css`` in the ``static`` subdirectory of the 527 ``my.package`` Python :term:`package`. 528 529Here's an example of the registration of a simple renderer factory via 530:meth:`~pyramid.config.Configurator.add_renderer`, where ``config`` is an 531instance of :meth:`pyramid.config.Configurator`: 532 533.. code-block:: python 534 535 config.add_renderer(name='amf', factory='my.package.MyAMFRenderer') 536 537Adding the above code to your application startup configuration will 538allow you to use the ``my.package.MyAMFRenderer`` renderer factory 539implementation in view configurations. Your application can use this 540renderer by specifying ``amf`` in the ``renderer`` attribute of a 541:term:`view configuration`: 542 543.. code-block:: python 544 :linenos: 545 546 from pyramid.view import view_config 547 548 @view_config(renderer='amf') 549 def myview(request): 550 return {'Hello':'world'} 551 552At startup time, when a :term:`view configuration` is encountered which has a 553``name`` attribute that does not contain a dot, the full ``name`` value is used 554to construct a renderer from the associated renderer factory. In this case, 555the view configuration will create an instance of an ``MyAMFRenderer`` for each 556view configuration which includes ``amf`` as its renderer value. The ``name`` 557passed to the ``MyAMFRenderer`` constructor will always be ``amf``. 558 559Here's an example of the registration of a more complicated renderer factory, 560which expects to be passed a filesystem path: 561 562.. code-block:: python 563 564 config.add_renderer(name='.jinja2', factory='my.package.MyJinja2Renderer') 565 566Adding the above code to your application startup will allow you to use the 567``my.package.MyJinja2Renderer`` renderer factory implementation in view 568configurations by referring to any ``renderer`` which *ends in* ``.jinja2`` in 569the ``renderer`` attribute of a :term:`view configuration`: 570 571.. code-block:: python 572 :linenos: 573 574 from pyramid.view import view_config 575 576 @view_config(renderer='templates/mytemplate.jinja2') 577 def myview(request): 578 return {'Hello':'world'} 579 580When a :term:`view configuration` is encountered at startup time which has a 581``name`` attribute that does contain a dot, the value of the name attribute is 582split on its final dot. The second element of the split is typically the 583filename extension. This extension is used to look up a renderer factory for 584the configured view. Then the value of ``renderer`` is passed to the factory 585to create a renderer for the view. In this case, the view configuration will 586create an instance of a ``MyJinja2Renderer`` for each view configuration which 587includes anything ending with ``.jinja2`` in its ``renderer`` value. The 588``name`` passed to the ``MyJinja2Renderer`` constructor will be the full value 589that was set as ``renderer=`` in the view configuration. 590 591Adding a Default Renderer 592~~~~~~~~~~~~~~~~~~~~~~~~~ 593 594To associate a *default* renderer with *all* view configurations (even ones 595which do not possess a ``renderer`` attribute), pass ``None`` as the ``name`` 596attribute to the renderer tag: 597 598.. code-block:: python 599 600 config.add_renderer(None, 'mypackage.json_renderer_factory') 601 602.. index:: 603 pair: renderer; changing 604 605Changing an Existing Renderer 606~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 607 608Pyramid supports overriding almost every aspect of its setup through its 609:ref:`Conflict Resolution <automatic_conflict_resolution>` mechanism. This 610means that, in most cases, overriding a renderer is as simple as using the 611:meth:`pyramid.config.Configurator.add_renderer` method to redefine the 612template extension. For example, if you would like to override the ``json`` 613renderer to specify a new renderer, you could do the following: 614 615.. code-block:: python 616 617 json_renderer = pyramid.renderers.JSON() 618 config.add_renderer('json', json_renderer) 619 620After doing this, any views registered with the ``json`` renderer will use the 621new renderer. 622 623.. index:: 624 pair: renderer; overriding at runtime 625 626Overriding a Renderer at Runtime 627-------------------------------- 628 629.. warning:: This is an advanced feature, not typically used by "civilians". 630 631In some circumstances, it is necessary to instruct the system to ignore the 632static renderer declaration provided by the developer in view configuration, 633replacing the renderer with another *after a request starts*. For example, an 634"omnipresent" XML-RPC implementation that detects that the request is from an 635XML-RPC client might override a view configuration statement made by the user 636instructing the view to use a template renderer with one that uses an XML-RPC 637renderer. This renderer would produce an XML-RPC representation of the data 638returned by an arbitrary view callable. 639 640To use this feature, create a :class:`~pyramid.events.NewRequest` 641:term:`subscriber` which sniffs at the request data and which conditionally 642sets an ``override_renderer`` attribute on the request itself, which in turn is 643the *name* of a registered renderer. For example: 644 645.. code-block:: python 646 :linenos: 647 648 from pyramid.events import subscriber 649 from pyramid.events import NewRequest 650 651 @subscriber(NewRequest) 652 def set_xmlrpc_params(event): 653 request = event.request 654 if (request.content_type == 'text/xml' 655 and request.method == 'POST' 656 and not 'soapaction' in request.headers 657 and not 'x-pyramid-avoid-xmlrpc' in request.headers): 658 params, method = parse_xmlrpc_request(request) 659 request.xmlrpc_params, request.xmlrpc_method = params, method 660 request.is_xmlrpc = True 661 request.override_renderer = 'xmlrpc' 662 return True 663 664The result of such a subscriber will be to replace any existing static renderer 665configured by the developer with a (notional, nonexistent) XML-RPC renderer, if 666the request appears to come from an XML-RPC client. 667