view doc/text-templates.txt @ 429:6911f3c5a7e8

Updated docs for code blocks and changed error handling.
author cmlenz
date Thu, 22 Mar 2007 17:00:09 +0000
parents ebc7c1a3bc4d
children ff7c72b52fb2
line wrap: on
line source
.. -*- mode: rst; encoding: utf-8 -*-

=============================
Genshi Text Template Language
=============================

In addition to the XML-based template language, Genshi provides a simple
text-based template language, intended for basic plain text generation needs.
The language is similar to Cheetah_ or Velocity_.

.. _cheetah: http://cheetahtemplate.org/
.. _velocity: http://jakarta.apache.org/velocity/

This document describes the template language and will be most useful as
reference to those developing Genshi text templates. Templates are XML files of some
kind (such as XHTML) that include processing directives_ (elements or
attributes identified by a separate namespace) that affect how the template is
rendered, and template expressions_ that are dynamically substituted by
variable data.


.. contents:: Contents
   :depth: 3
.. sectnum::

----------
Python API
----------

The Python code required for templating with Genshi is generally based on the
following pattern:

* Attain a ``TextTemplate`` object from a string or file object containing the
  template source. This can either be done directly, or through a
  ``TemplateLoader`` instance.
* Call the ``generate()`` method of the template, passing any data that should
  be made available to the template as keyword arguments.
* Serialize the resulting stream using its ``render()`` method.

For example::

  from genshi.template import TextTemplate

  tmpl = TextTemplate('$title')
  stream = tmpl.generate(title='Hello, world!')
  print stream.render('text')

That code would produce the following output::

  Hello, world!

Using a template loader provides the advantage that “compiled” templates are
automatically cached, and only parsed again when the template file changes::

  from genshi.template import TemplateLoader

  loader = TemplateLoader([templates_dir])
  tmpl = loader.load('test.txt' cls=TextTemplate)
  stream = tmpl.generate(title='Hello, world!')
  print stream.render('text')


.. _`expressions`:

--------------------
Template Expressions
--------------------

Python_ expressions can be used in text and as arguments to directives_. An expression is substituted with the result of its evaluation against the
template data. Expressions need to prefixed with a dollar sign (``$``) and 
usually enclosed in curly braces (``{…}``).

.. _python: http://www.python.org/

If the expression starts with a letter and contains only letters, digits, dots,
and underscores, the curly braces may be omitted. In all other cases, the
braces are required so that the template processor knows where the expression
ends::

  >>> from genshi.template import TextTemplate
  >>> tmpl = TextTemplate('${items[0].capitalize()} item')
  >>> print tmpl.generate(items=['first', 'second'])
  First item

Expressions support the full power of Python. In addition, it is possible to
access items in a dictionary using “dotted notation” (i.e. as if they were
attributes), and vice-versa (i.e. access attributes as if they were items in
a dictionary)::

  >>> from genshi.template import TextTemplate
  >>> tmpl = TextTemplate('${dict.foo}')
  >>> print tmpl.generate(dict={'foo': 'bar'})
  bar

Because there are two ways to access either attributes or items, expressions
do not raise the standard ``AttributeError`` or ``IndexError`` exceptions, but
rather an exception of the type ``UndefinedError``. The same kind of error is
raised when you try to access a top-level variable that is not in the context
data.

Built-in Functions & Types
==========================

The following functions and types are available by default in template code, in
addition to the standard built-ins that are available to all Python code.

``defined(name)``
-----------------
 
This function determines whether a variable of the specified name exists in
the context data, and returns ``True`` if it does.
 
``value_of(name, default=None)``
--------------------------------

This function returns the value of the variable with the specified name if
such a variable is defined, and returns the value of the ``default``
parameter if no such variable is defined.

``Markup(text)``
----------------

The ``Markup`` type marks a given string as being safe for inclusion in markup,
meaning it will *not* be escaped in the serialization stage. Use this with care,
as not escaping a user-provided string may allow malicious users to open your
web site to cross-site scripting attacks.


.. _`directives`:

-------------------
Template Directives
-------------------

Directives are lines starting with a ``#`` character followed immediately by
the directive name. They can affect how the template is rendered in a number of
ways: Genshi provides directives for conditionals and looping, among others.

Directives must be on separate lines, and the ``#`` character must be be the
first non-whitespace character on that line. Each directive must be “closed”
using a ``#end`` marker. You can add after the ``#end`` marker, for example to
document which directive is being closed, or even the expression associated with 
that directive. Any text after ``#end`` (but on the same line) is  ignored, 
and effectively treated as a comment.

If you want to include a literal ``#`` in the output, you need to escape it
by prepending a backslash character (``\``). Note that this is **not** required 
if the ``#`` isn't immediately followed by a letter, or it isn't the first
non-whitespace character on the line.


Conditional Sections
====================

.. _`#if`:

``#if``
---------

The content is only rendered if the expression evaluates to a truth value::

  #if foo
    ${bar}
  #end

Given the data ``foo=True`` and ``bar='Hello'`` in the template context, this
would produce::

    Hello


.. _`#choose`:
.. _`#when`:
.. _`#otherwise`:

``#choose``
-------------

The ``#choose`` directive, in combination with the directives ``#when`` and
``#otherwise`` provides advanced contional processing for rendering one of
several alternatives. The first matching ``#when`` branch is rendered, or, if
no ``#when`` branch matches, the ``#otherwise`` branch is be rendered.

If the ``#choose`` directive has no argument the nested ``#when`` directives
will be tested for truth::

  The answer is:
  #choose
    #when 0 == 1
      0
    #end
    #when 1 == 1
      1
    #end
    #otherwise
      2
    #end
  #end

This would produce the following output::

  The answer is:
      1

If the ``#choose`` does have an argument, the nested ``#when`` directives will
be tested for equality to the parent ``#choose`` value::

  The answer is:
  #choose 1
    #when 0
      0
    #end
    #when 1
      1
    #end
    #otherwise
      2
    #end
  #end

This would produce the following output::

  The answer is:
      1


Looping
=======

.. _`#for`:

``#for``
----------

The content is repeated for every item in an iterable::

  Your items:
  #for item in items
    * ${item}
  #end

Given ``items=[1, 2, 3]`` in the context data, this would produce::

  Your items
    * 1
    * 2
    * 3


Snippet Reuse
=============

.. _`#def`:
.. _`macros`:

``#def``
----------

The ``#def`` directive can be used to create macros, i.e. snippets of template
text that have a name and optionally some parameters, and that can be inserted
in other places::

  #def greeting(name)
    Hello, ${name}!
  #end
  ${greeting('world')}
  ${greeting('everyone else')}

The above would be rendered to::

    Hello, world!
    Hello, everyone else!

If a macro doesn't require parameters, it can be defined as well as called
without the parenthesis. For example::

  #def greeting
    Hello, world!
  #end
  ${greeting}

The above would be rendered to::

    Hello, world!


Variable Binding
================

.. _`#with`:

``#with``
-----------

The ``#with`` directive lets you assign expressions to variables, which can
be used to make expressions inside the directive less verbose and more
efficient. For example, if you need use the expression ``author.posts`` more
than once, and that actually results in a database query, assigning the results
to a variable using this directive would probably help.

For example::

  Magic numbers!
  #with y=7; z=x+10
    $x $y $z
  #end

Given ``x=42`` in the context data, this would produce::

  Magic numbers!
    42 7 52

Note that if a variable of the same name already existed outside of the scope
of the ``#with`` directive, it will **not** be overwritten. Instead, it will
have the same value it had prior to the ``#with`` assignment. Effectively,
this means that variables are immutable in Genshi.


.. _comments:

--------
Comments
--------

Lines where the first non-whitespace characters are ``##`` are removed from
the output, and can thus be used for comments. This can be escaped using a
backslash.
Copyright (C) 2012-2017 Edgewall Software