Examples

Download full examples code from GitHub.

Simple

A simple TAL example with METAL macros.

Install:

pip install aiohttp-tal

Run:

python simple.py
simple.py
from pathlib import Path

from aiohttp import web
import aiohttp_tal
from chameleon import PageTemplateLoader


THIS_DIR = Path(__file__).parent


@aiohttp_tal.template('index.html')
async def index(request):
    # Note: we return a dict not a response because of the @template decorator
    return {
        'title': request.app['name'],
        'intro': "Success! you've setup a basic aiohttp app with TAL.",
        }


@aiohttp_tal.template('translation.html')
async def page(request):
    return {
        'title': 'First page',
        }


async def create_app():
    app = web.Application()
    app.update(name='Testing aiohttp TAL')

    tal_loader = PageTemplateLoader(str(THIS_DIR / 'templates'),
                                    auto_reload=True  # debugging
                                    )
    aiohttp_tal.setup(app, loader=tal_loader)

    app.add_routes([web.static('/static', str(THIS_DIR / 'static'))])
    app['static_root_url'] = '/static'
    app.router.add_get('/', index, name='index')
    app.router.add_get('/page', page, name='translation')

    return app


if __name__ == '__main__':
    web.run_app(create_app(), host='127.0.0.1', port=8080)

Macro

templates/base.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-us"
      xmlns:tal="http://xml.zope.org/namespaces/tal"
      xmlns:metal="http://xml.zope.org/namespaces/metal"
      metal:define-macro="master">
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>${app.name}</title>
  <link href="../static/style.css" tal:attributes="href static('style.css')" rel="stylesheet" />
</head>
<body>
  <main>
    <h1>${title}</h1>
    <div metal:define-slot="content"></div>
  </main>
</body>
</html>

Page template

templates/index.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      metal:use-macro="load: base.html">
<head>
  <link href="../static/style.css" rel="stylesheet" tal:condition="nothing" />
</head>
<body>
<div metal:fill-slot="content">
  <p>${intro}</p>

  <p>
    To demonstrate a little of the functionality of aiohttp TAL.
  </p>
  <b>
    <a href="translation.html" tal:attributes="href url('translation')">View first page</a>
  </b>
</div>
</body>
</html>

Translation (I18N)

See TAL I18N and aiohttp_babel.

Install:

pip install aiohttp-tal aiohttp_babel babel-lingua-chameleon

Run:

python translation.py
translation.py
"""

First time:

* pybabel extract -F babel.cfg -o locales/mydomain.pot .
* pybabel init -D mydomain -i locales/mydomain.pot -d locales -l ca
* pybabel init -D mydomain -i locales/mydomain.pot -d locales -l fr_fr
* pybabel compile -D mydomain -d locales

Updates:

* pybabel extract -F babel.cfg -o locales/mydomain.pot .
* pybabel update -D mydomain -i locales/mydomain.pot -d locales
* pybabel compile -D mydomain -d locales

"""
from pathlib import Path

from aiohttp import web
from aiohttp_babel.locale import load_gettext_translations, set_default_locale
from aiohttp_babel.middlewares import babel_middleware, _
import aiohttp_tal
from chameleon import PageTemplateLoader


THIS_DIR = Path(__file__).parent

set_default_locale('en_GB')
load_gettext_translations(str(THIS_DIR / 'locales'), 'mydomain')


@aiohttp_tal.template('index.html')
async def index(request):
    return {
        'title': request.app['name'],
        'intro': "Success! you've setup a basic aiohttp app with TAL.",
        }


@aiohttp_tal.template('translation.html')
async def translation(request):
    return {
        'title': _('First page'),
        'request': request,
        }


def translate(msgid, domain=None, mapping=None, context=None,
              target_language=None, default=None):
    # _(message, plural_message=None, count=None, **kwargs):
    return str(_(msgid))


async def create_app():
    app = web.Application(middlewares=[babel_middleware])
    app.update(name='Testing aiohttp TAL')

    tal_loader = PageTemplateLoader(str(THIS_DIR / 'templates'),
                                    translate=translate,
                                    auto_reload=True  # debugging
                                    )
    aiohttp_tal.setup(app, loader=tal_loader)

    app.add_routes([web.static('/static', str(THIS_DIR / 'static'))])
    app['static_root_url'] = '/static'
    app.router.add_get('/', index, name='index')
    app.router.add_get('/translation', translation, name='translation')

    return app


if __name__ == '__main__':
    web.run_app(create_app(), host='127.0.0.1', port=8080)

Page template with i18n

templates/translation.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:tal="http://xml.zope.org/namespaces/tal"
      xmlns:metal="http://xml.zope.org/namespaces/metal"
      xmlns:i18n="http://xml.zope.org/namespaces/i18n"
      metal:use-macro="load: base.html"
      i18n:domain="mydomain">
<head>
  <link href="../static/style.css" tal:attributes="href static('style.css')" rel="stylesheet" tal:condition="nothing"/>
</head>
<body>
<div metal:fill-slot="content">


<p i18n:translate="">The first page</p>

<p tal:condition="request.locale|nothing">
  <span tal:define="datetime import: datetime;
                    today datetime.datetime.now();"
        tal:content="request.locale.format_datetime(today)">
	1/1/1970
  </span>
</p>


<b>
<a href="index.html" tal:attributes="href url('index')"
   title="Go to index" i18n:attributes="title"
   i18n:translate="">
  View Index
</a>
</b>


<hr/>

<p tal:condition="request.locale|nothing">
<a href="" onclick="document.cookie='locale=ca'">ca</a>
<a href="" onclick="document.cookie='locale=fr_FR'">fr</a>
<a href="" onclick="document.cookie='locale=en'">en</a>
</p>

</div>
</body>
</html>