Skip to content

Commit

Permalink
Add mako rendering example and link to examples in docs
Browse files Browse the repository at this point in the history
  • Loading branch information
sloria committed Oct 27, 2015
1 parent 1520216 commit 57f0968
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 4 deletions.
11 changes: 7 additions & 4 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,18 @@ Release v\ |version|. (:ref:`Changelog <changelog>`)
)
Install
=======
-------
::

$ pip install aiohttp_utils

Utilities
---------

Below is a listing of available utility modules.
**Ready to get started?** Go on to one of the the usage guides below or check out some `examples <https://github.com/sloria/aiohttp_utils/tree/master/examples>`_.

Guides
------

Below are usage guides for each of the modules.

.. toctree::
:maxdepth: 1
Expand Down
93 changes: 93 additions & 0 deletions examples/mako_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
"""Example of using content negotiation to support HTML representations, using
Mako for templating. Also demonstrates app configuration.
Start the app with
::
$ pip install mako
$ python examples/mako_example.py
Try it out:
::
$ pip install httpie
$ http :8000/ Accept:application/json
$ http :8000/ Accept:text/html
"""
from collections import OrderedDict, Mapping
from asyncio import coroutine

from aiohttp import web
from aiohttp_utils import Response, negotiation, run

from mako.lookup import TemplateLookup

##### Templates #####

lookup = TemplateLookup()
# Note: In a real app, this would be in a file.
template = """
<html>
<body>
<h1>${message}</h1>
</body>
</html>
"""
lookup.put_string('index.html', template)

##### Handlers #####

@coroutine
def index(request):
return Response({
'message': 'Hello ' + request.GET.get('name', 'World')
})

##### Custom router #####

class RoutingWithTemplating(web.UrlDispatcher):
"""Optionally save a template name on a handler function's __dict__."""

def add_route(self, method, path, handler, template: str=None, **kwargs):
if template:
handler.__dict__['template'] = template
super().add_route(method, path, handler, **kwargs)

##### Renderer #####

def render_mako(request, data, handler):
template_name = handler.__dict__.get('template', None)
if not template_name:
raise web.HTTPNotAcceptable(text='text/html not supported.')
if not isinstance(data, Mapping):
raise web.HTTPInternalServerError(
text="context should be mapping, not {}".format(type(data)))
template = request.app['mako_lookup'].get_template(template_name)
text = template.render_unicode(**data)
return web.Response(text=text, content_type=request['selected_media_type'])

##### Configuration #####

CONFIG = {
'AIOHTTP_UTILS': {
'RENDERERS': OrderedDict([
('application/json', negotiation.render_json),
('text/html', render_mako),
])
}
}

##### Application #####

app = web.Application(router=RoutingWithTemplating(), debug=True)
app['mako_lookup'] = lookup
app.update(CONFIG)
negotiation.setup(app)
app.router.add_route('GET', '/', index, template='index.html')

if __name__ == "__main__":
run(
app,
app_uri='examples.mako_example:app',
reload=True,
port=8000,
)
23 changes: 23 additions & 0 deletions tests/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import pytest

from examples.kitchen_sink import app as kitchen_sink_app
from examples.mako_example import app as mako_app

class TestKitchenSinkApp:

Expand Down Expand Up @@ -34,3 +35,25 @@ def test_api_index_merge_slashes(self, client):
assert res.status_code == 200
assert res.request.path == '/api/'

class TestMakoApp:

@pytest.fixture()
def client(self, loop, create_client):
mako_app._loop = loop
return create_client(mako_app)

def test_json_request(self, client):
res = client.get('/', headers={'Accept': 'application/json'})
assert res.content_type == 'application/json'
assert res.json == {'message': 'Hello World'}

def test_json_request_with_query_params(self, client):
res = client.get('/?name=Ada', headers={'Accept': 'application/json'})
assert res.content_type == 'application/json'
assert res.json == {'message': 'Hello Ada'}

def test_html_request(self, client):
res = client.get('/', headers={'Accept': 'text/html'})
assert res.status_code == 200
assert res.content_type == 'text/html'
assert res.html.find('h1').text == 'Hello World'

0 comments on commit 57f0968

Please sign in to comment.