Improve documentation for @expose('json').
This commit is contained in:
parent
1a0a72f0b1
commit
b41300b5a7
|
@ -77,27 +77,51 @@ Exposing Controllers
|
|||
You tell Pecan which methods in a class are publically-visible via
|
||||
:func:`~pecan.decorators.expose`. If a method is *not* decorated with
|
||||
:func:`~pecan.decorators.expose`, Pecan will never route a request to it.
|
||||
:func:`~pecan.decorators.expose` accepts three optional parameters, some of
|
||||
which can impact routing and the content type of the response body.
|
||||
|
||||
:func:`~pecan.decorators.expose` can be used in a variety of ways. The
|
||||
simplest case involves passing no arguments. In this scenario, the controller
|
||||
returns a string representing the HTML response body.
|
||||
|
||||
::
|
||||
|
||||
from pecan import expose
|
||||
|
||||
class RootController(object):
|
||||
@expose(
|
||||
template = None,
|
||||
content_type = 'text/html',
|
||||
generic = False
|
||||
)
|
||||
@expose()
|
||||
def hello(self):
|
||||
return 'Hello World'
|
||||
|
||||
|
||||
Let's look at an example using ``template`` and ``content_type``:
|
||||
A more common use case is to :ref:`specify a template and a namespace
|
||||
<templates>`::
|
||||
|
||||
from pecan import expose
|
||||
|
||||
class RootController(object):
|
||||
@expose('html_template.mako')
|
||||
def hello(self):
|
||||
return {'msg': 'Hello!'}
|
||||
|
||||
::
|
||||
|
||||
<!-- html_template.mako -->
|
||||
<html>
|
||||
<body>${msg}</body>
|
||||
</html>
|
||||
|
||||
Pecan also has built-in support for a special :ref:`JSON renderer
|
||||
<expose_json>`, which translates template namespaces into rendered JSON text::
|
||||
|
||||
from pecan import expose
|
||||
|
||||
class RootController(object):
|
||||
@expose('json')
|
||||
def hello(self):
|
||||
return {'msg': 'Hello!'}
|
||||
|
||||
:func:`~pecan.decorators.expose` calls can also be stacked, which allows you to
|
||||
serialize content differently depending on how the content is requested::
|
||||
|
||||
from pecan import expose
|
||||
|
||||
class RootController(object):
|
||||
|
@ -115,14 +139,15 @@ different arguments.
|
|||
@expose('json')
|
||||
|
||||
The first tells Pecan to serialize the response namespace using JSON
|
||||
serialization when the client requests ``/hello.json``.
|
||||
serialization when the client requests ``/hello.json`` or if an
|
||||
``Accept: application/json`` header is present.
|
||||
|
||||
::
|
||||
|
||||
@expose('text_template.mako', content_type='text/plain')
|
||||
|
||||
The second tells Pecan to use the ``text_template.mako`` template file when the
|
||||
client requests ``/hello.txt``.
|
||||
client requests ``/hello.txt`` or asks for text/plain via an ``Accept`` header.
|
||||
|
||||
::
|
||||
|
||||
|
@ -130,7 +155,8 @@ client requests ``/hello.txt``.
|
|||
|
||||
The third tells Pecan to use the ``html_template.mako`` template file when the
|
||||
client requests ``/hello.html``. If the client requests ``/hello``, Pecan will
|
||||
use the ``text/html`` content type by default.
|
||||
use the ``text/html`` content type by default; in the absense of an explicit
|
||||
content type, Pecan assumes the client wants HTML.
|
||||
|
||||
.. seealso::
|
||||
|
||||
|
|
|
@ -95,6 +95,7 @@ template, and :func:`~pecan.core.render` returns the rendered output as text.
|
|||
def controller(self):
|
||||
return render('my_template.html', dict(message='I am the namespace'))
|
||||
|
||||
.. _expose_json:
|
||||
|
||||
The JSON Renderer
|
||||
-----------------
|
||||
|
@ -141,3 +142,11 @@ your application's configuration::
|
|||
},
|
||||
# ...
|
||||
}
|
||||
|
||||
...and specify the renderer in the :func:`~pecan.decorators.expose` method::
|
||||
|
||||
class RootController(object):
|
||||
|
||||
@expose('my_renderer:template.html')
|
||||
def index(self):
|
||||
return dict(name='Bob')
|
||||
|
|
|
@ -32,7 +32,9 @@ def expose(template=None,
|
|||
access via HTTP, and to configure that access.
|
||||
|
||||
:param template: The path to a template, relative to the base template
|
||||
directory.
|
||||
directory. Can also be passed a string representing
|
||||
a special or custom renderer, such as ``'json'`` for
|
||||
:ref:`expose_json`.
|
||||
:param content_type: The content-type to use for this template.
|
||||
:param generic: A boolean which flags this as a "generic" controller,
|
||||
which uses generic functions based upon
|
||||
|
|
|
@ -20,7 +20,7 @@ from pecan import (
|
|||
abort, make_app, override_template, render, route
|
||||
)
|
||||
from pecan.templating import (
|
||||
_builtin_renderers as builtin_renderers, error_formatters
|
||||
_builtin_renderers as builtin_renderers, error_formatters, MakoRenderer
|
||||
)
|
||||
from pecan.decorators import accept_noncanonical
|
||||
from pecan.tests import PecanTestCase
|
||||
|
@ -1920,6 +1920,36 @@ class TestEngines(PecanTestCase):
|
|||
result = dict(loads(r.body.decode()))
|
||||
assert result == expected_result
|
||||
|
||||
def test_custom_renderer(self):
|
||||
|
||||
class RootController(object):
|
||||
@expose('backwards:mako.html')
|
||||
def index(self, name='Joe'):
|
||||
return dict(name=name)
|
||||
|
||||
class BackwardsRenderer(MakoRenderer):
|
||||
# Custom renderer that reverses all string namespace values
|
||||
def render(self, template_path, namespace):
|
||||
namespace = dict(
|
||||
(k, v[::-1])
|
||||
for k, v in namespace.items()
|
||||
)
|
||||
return super(BackwardsRenderer, self).render(template_path,
|
||||
namespace)
|
||||
|
||||
app = TestApp(Pecan(
|
||||
RootController(),
|
||||
template_path=self.template_path,
|
||||
custom_renderers={'backwards': BackwardsRenderer}
|
||||
))
|
||||
r = app.get('/')
|
||||
assert r.status_int == 200
|
||||
assert b_("<h1>Hello, eoJ!</h1>") in r.body
|
||||
|
||||
r = app.get('/index.html?name=Tim')
|
||||
assert r.status_int == 200
|
||||
assert b_("<h1>Hello, miT!</h1>") in r.body
|
||||
|
||||
def test_override_template(self):
|
||||
class RootController(object):
|
||||
@expose('foo.html')
|
||||
|
|
Loading…
Reference in New Issue