.. currentmodule:: fiole Build templates =============== *Parts of this page are converted from the wheezy.template documentation. Thank you to the author.* (:ref:`akorn`) ``Fiole`` comes with a decent template engine. It supports the usual features of well known engines (*Mako*, *Jinja2*). The engine is derived from the wonderful `wheezy.template`_ package. It retains the same design goals: * intuitive, use the full power of Python * inherit your templates (``%extends``, ``%include`` and ``%import``) * stay *blazingly* `fast `__. In a nutshell, the syntax looks as simple as `Bottle SimpleTemplate`_: * ``{{ ... }}`` executes the enclosed :ref:`expression` and inserts the result. * Use the ``|e`` filter to convert any of ``& < > " '`` to HTML-safe sequences. * Switch to auto-escaping with ``fiole.engine.default_filters = ['e']`` and use ``|n`` to disable escaping (and default filters) for an expression. * A single percent ``%`` at the beginning of the line identifies a :ref:`template directive` or :ref:`Python code`. (except if it is repeated: ``%%``) * Spaces and indentation around the ``%`` special char are ignored. * A backslash ``\`` at the end of a line will skip the line ending. Simple template: .. code-block:: mako %require(user, items) Welcome, {{user.name}}! %if items: %for i in items: {{i.name}}: {{i.price}}. %endfor %else: No item found. %endif .. contents:: :local: :depth: 2 :backlinks: top .. _Bottle SimpleTemplate: http://bottlepy.org/docs/dev/stpl.html .. _wheezy.template: http://wheezytemplate.readthedocs.org/en/latest/ .. _template_expressions: Template loading ---------------- This is a basic example for a route mapped to a template:: @get('/') @get('/hello/') def hello(request, name=None): return render_template( source='Hello {{party.title() if party else "stranger"}}!', party=name) In this case the template is not cached. It is built again for each request. In order to activate the cache, the string template should be assigned to a name. The previous example becomes:: # Preload the cache get_template('hello_tpl', source="""Hello {{party.title() if party else "stranger"}}!""", require=['party']) @get('/') @get('/hello/') def hello(request, name=None): return render_template('hello_tpl', party=name) Templates can be saved to files in the ``./templates/`` folder of the project. Then they are loaded by filename and cached in memory:: @get('/') def index(request): return render_template('hello.tmpl', party='World') Inline expressions ------------------ Variables ~~~~~~~~~ The variables which need to be extracted from the context are listed in the ``require`` directive. These names become visible to the end of the template scope (a template is like a Python function). The application passes variables to the template via context: .. code-block:: mako %require(var1, var2) {{ var1 }} ... {{ var2 }} For string templates, you can declare the variables using the ``require`` keyword argument:: >>> hello_tmpl = get_template(source='Hello {{ party.capitalize() }}!', require=['party']) >>> hello_tmpl.render(party='WORLD') u'Hello World!' >>> hello_tmpl.render({'party': 'world'}) u'Hello World!' This declaration is omitted when rendering the string directly:: >>> render_template(source='Hello {{party}}!', party='World') u'Hello World!' >>> # >>> render_template(source='Hello {{ party.capitalize() }}!', party='world') u'Hello World!' Variable syntax is not limited to a single name access. You are able to use the full power of Python to access items in dictionary, attributes, function calls, etc... Filters ~~~~~~~ Variables can be formatted by filters. Filters are separated from the variable by the ``|`` symbol. Filter syntax: .. code-block:: mako {{ variable_name|filter1|filter2 }} The filters are applied from left to right so above syntax is equivalent to the following call: .. code-block:: mako {{ filter2(filter1(variable_name)) }} The built-in filter ``|e`` converts any of ``& < > " '`` to HTML-safe sequences ``& < > " '``. You can define and use custom filters. Here is an example how to switch to a different implementation for the html escape filter:: try: from webext import escape_html engine.global_vars['escape'] = escape_html except ImportError: pass It tries to import an optimized version of html escape from the `Webext`_ package and assigns it to the ``escape`` global variable, which is aliased as ``e`` filter. The built-in ``escape`` is pure Python. An example which demonstrates the standard ``|e`` filter:: >>> render_template('This: {{ data | e }}', data='"Hello small\' World!" ... & farther') u'This: "Hello small' <i>World!<i>" ... & farther' You can enable auto-escaping by default, then use ``|n`` as the last filter to bypass the default filters:: >>> engine.default_filters = ['e'] >>> render_template(source='Hello {{ party.capitalize() }}', ... party='