cmlenz@241: .. -*- mode: rst; encoding: utf-8 -*- cmlenz@241: cmlenz@241: ============================= cmlenz@241: Genshi Text Template Language cmlenz@241: ============================= cmlenz@241: cmlenz@241: In addition to the XML-based template language, Genshi provides a simple cmlenz@241: text-based template language, intended for basic plain text generation needs. cmlenz@820: The language is similar to the Django_ template language. cmlenz@241: cmlenz@241: This document describes the template language and will be most useful as cmlenz@500: reference to those developing Genshi text templates. Templates are text files of cmlenz@500: some kind that include processing directives_ that affect how the template is cmlenz@500: rendered, and template expressions that are dynamically substituted by cmlenz@241: variable data. cmlenz@241: cmlenz@500: See `Genshi Templating Basics `_ for general information on cmlenz@500: embedding Python code in templates. cmlenz@500: cmlenz@820: .. note:: Actually, Genshi currently has two different syntaxes for text cmlenz@820: templates languages: One implemented by the class ``OldTextTemplate`` cmlenz@820: and another implemented by ``NewTextTemplate``. This documentation cmlenz@820: concentrates on the latter, which is planned to completely replace the cmlenz@820: older syntax. The older syntax is briefly described under legacy_. cmlenz@820: cmlenz@820: .. _django: http://www.djangoproject.com/ cmlenz@241: cmlenz@241: .. contents:: Contents cmlenz@241: :depth: 3 cmlenz@241: .. sectnum:: cmlenz@241: cmlenz@241: cmlenz@241: .. _`directives`: cmlenz@241: cmlenz@241: ------------------- cmlenz@241: Template Directives cmlenz@241: ------------------- cmlenz@241: cmlenz@820: Directives are template commands enclosed by ``{% ... %}`` characters. They can cmlenz@820: affect how the template is rendered in a number of ways: Genshi provides cmlenz@820: directives for conditionals and looping, among others. cmlenz@241: cmlenz@820: Each directive must be terminated using an ``{% end %}`` marker. You can add cmlenz@820: a string inside the ``{% end %}`` marker, for example to document which cmlenz@820: directive is being closed, or even the expression associated with that cmlenz@820: directive. Any text after ``end`` inside the delimiters is ignored, and cmlenz@820: effectively treated as a comment. cmlenz@241: cmlenz@820: If you want to include a literal delimiter in the output, you need to escape it cmlenz@820: by prepending a backslash character (``\``). cmlenz@244: cmlenz@241: cmlenz@241: Conditional Sections cmlenz@241: ==================== cmlenz@241: cmlenz@820: .. _`if`: cmlenz@241: cmlenz@820: ``{% if %}`` cmlenz@820: ------------ cmlenz@241: cmlenz@820: The content is only rendered if the expression evaluates to a truth value: cmlenz@820: cmlenz@820: .. code-block:: genshitext cmlenz@820: cmlenz@820: {% if foo %} cmlenz@241: ${bar} cmlenz@820: {% end %} cmlenz@241: cmlenz@241: Given the data ``foo=True`` and ``bar='Hello'`` in the template context, this cmlenz@241: would produce:: cmlenz@241: cmlenz@241: Hello cmlenz@241: cmlenz@241: cmlenz@820: .. _`choose`: cmlenz@820: .. _`when`: cmlenz@820: .. _`otherwise`: cmlenz@241: cmlenz@820: ``{% choose %}`` cmlenz@820: ---------------- cmlenz@241: cmlenz@820: The ``choose`` directive, in combination with the directives ``when`` and cmlenz@820: ``otherwise``, provides advanced contional processing for rendering one of cmlenz@820: several alternatives. The first matching ``when`` branch is rendered, or, if cmlenz@820: no ``when`` branch matches, the ``otherwise`` branch is be rendered. cmlenz@820: cmlenz@820: If the ``choose`` directive has no argument the nested ``when`` directives will cmlenz@820: be tested for truth: cmlenz@820: cmlenz@820: .. code-block:: genshitext cmlenz@241: cmlenz@241: The answer is: cmlenz@820: {% choose %} cmlenz@820: {% when 0 == 1 %}0{% end %} cmlenz@820: {% when 1 == 1 %}1{% end %} cmlenz@820: {% otherwise %}2{% end %} cmlenz@820: {% end %} cmlenz@241: cmlenz@241: This would produce the following output:: cmlenz@241: cmlenz@241: The answer is: cmlenz@820: 1 cmlenz@241: cmlenz@820: If the ``choose`` does have an argument, the nested ``when`` directives will cmlenz@820: be tested for equality to the parent ``choose`` value: cmlenz@820: cmlenz@820: .. code-block:: genshitext cmlenz@241: cmlenz@241: The answer is: cmlenz@820: {% choose 1 %}\ cmlenz@820: {% when 0 %}0{% end %}\ cmlenz@820: {% when 1 %}1{% end %}\ cmlenz@820: {% otherwise %}2{% end %}\ cmlenz@820: {% end %} cmlenz@241: cmlenz@241: This would produce the following output:: cmlenz@241: cmlenz@241: The answer is: cmlenz@241: 1 cmlenz@241: cmlenz@241: cmlenz@241: Looping cmlenz@241: ======= cmlenz@241: cmlenz@820: .. _`for`: cmlenz@241: cmlenz@820: ``{% for %}`` cmlenz@820: ------------- cmlenz@241: cmlenz@820: The content is repeated for every item in an iterable: cmlenz@820: cmlenz@820: .. code-block:: genshitext cmlenz@241: cmlenz@241: Your items: cmlenz@820: {% for item in items %}\ cmlenz@241: * ${item} cmlenz@820: {% end %} cmlenz@241: cmlenz@241: Given ``items=[1, 2, 3]`` in the context data, this would produce:: cmlenz@241: cmlenz@241: Your items cmlenz@241: * 1 cmlenz@241: * 2 cmlenz@241: * 3 cmlenz@241: cmlenz@241: cmlenz@241: Snippet Reuse cmlenz@241: ============= cmlenz@241: cmlenz@820: .. _`def`: cmlenz@241: .. _`macros`: cmlenz@241: cmlenz@820: ``{% def %}`` cmlenz@820: ------------- cmlenz@241: cmlenz@820: The ``def`` directive can be used to create macros, i.e. snippets of template cmlenz@241: text that have a name and optionally some parameters, and that can be inserted cmlenz@820: in other places: cmlenz@241: cmlenz@820: .. code-block:: genshitext cmlenz@820: cmlenz@820: {% def greeting(name) %} cmlenz@241: Hello, ${name}! cmlenz@820: {% end %} cmlenz@241: ${greeting('world')} cmlenz@241: ${greeting('everyone else')} cmlenz@241: cmlenz@241: The above would be rendered to:: cmlenz@241: cmlenz@241: Hello, world! cmlenz@241: Hello, everyone else! cmlenz@241: cmlenz@820: If a macro doesn't require parameters, it can be defined without the cmlenz@820: parenthesis. For example: cmlenz@241: cmlenz@820: .. code-block:: genshitext cmlenz@820: cmlenz@820: {% def greeting %} cmlenz@241: Hello, world! cmlenz@820: {% end %} cmlenz@820: ${greeting()} cmlenz@241: cmlenz@241: The above would be rendered to:: cmlenz@241: cmlenz@241: Hello, world! cmlenz@241: cmlenz@241: cmlenz@500: .. _includes: cmlenz@820: .. _`include`: cmlenz@500: cmlenz@820: ``{% include %}`` cmlenz@820: ----------------- cmlenz@500: cmlenz@500: To reuse common parts of template text across template files, you can include cmlenz@820: other files using the ``include`` directive: cmlenz@500: cmlenz@820: .. code-block:: genshitext cmlenz@820: cmlenz@820: {% include base.txt %} cmlenz@500: cmlenz@500: Any content included this way is inserted into the generated output. The cmlenz@500: included template sees the context data as it exists at the point of the cmlenz@500: include. `Macros`_ in the included template are also available to the including cmlenz@500: template after the point it was included. cmlenz@500: cmlenz@500: Include paths are relative to the filename of the template currently being cmlenz@500: processed. So if the example above was in the file "``myapp/mail.txt``" cmlenz@500: (relative to the template search path), the include directive would look for cmlenz@500: the included file at "``myapp/base.txt``". You can also use Unix-style cmlenz@500: relative paths, for example "``../base.txt``" to look in the parent directory. cmlenz@500: cmlenz@820: Just like other directives, the argument to the ``include`` directive accepts cmlenz@500: any Python expression, so the path to the included template can be determined cmlenz@820: dynamically: cmlenz@500: cmlenz@820: .. code-block:: genshitext cmlenz@820: cmlenz@820: {% include ${'%s.txt' % filename} %} cmlenz@500: cmlenz@500: Note that a ``TemplateNotFound`` exception is raised if an included file can't cmlenz@500: be found. cmlenz@500: cmlenz@500: .. note:: The include directive for text templates was added in Genshi 0.5. cmlenz@500: cmlenz@500: cmlenz@241: Variable Binding cmlenz@241: ================ cmlenz@241: cmlenz@820: .. _`with`: cmlenz@241: cmlenz@820: ``{% with %}`` cmlenz@820: -------------- cmlenz@241: cmlenz@820: The ``{% with %}`` directive lets you assign expressions to variables, which can cmlenz@241: be used to make expressions inside the directive less verbose and more cmlenz@241: efficient. For example, if you need use the expression ``author.posts`` more cmlenz@241: than once, and that actually results in a database query, assigning the results cmlenz@241: to a variable using this directive would probably help. cmlenz@241: cmlenz@820: For example: cmlenz@820: cmlenz@820: .. code-block:: genshitext cmlenz@241: cmlenz@241: Magic numbers! cmlenz@820: {% with y=7; z=x+10 %} cmlenz@241: $x $y $z cmlenz@820: {% end %} cmlenz@241: cmlenz@241: Given ``x=42`` in the context data, this would produce:: cmlenz@241: cmlenz@241: Magic numbers! cmlenz@241: 42 7 52 cmlenz@241: cmlenz@241: Note that if a variable of the same name already existed outside of the scope cmlenz@820: of the ``with`` directive, it will **not** be overwritten. Instead, it will cmlenz@820: have the same value it had prior to the ``with`` assignment. Effectively, cmlenz@241: this means that variables are immutable in Genshi. cmlenz@241: cmlenz@241: cmlenz@820: .. _whitespace: cmlenz@820: cmlenz@820: --------------------------- cmlenz@820: White-space and Line Breaks cmlenz@820: --------------------------- cmlenz@820: cmlenz@820: Note that space or line breaks around directives is never automatically removed. cmlenz@820: Consider the following example: cmlenz@820: cmlenz@820: .. code-block:: genshitext cmlenz@820: cmlenz@820: {% for item in items %} cmlenz@820: {% if item.visible %} cmlenz@820: ${item} cmlenz@820: {% end %} cmlenz@820: {% end %} cmlenz@820: cmlenz@820: This will result in two empty lines above and beneath every item, plus the cmlenz@820: spaces used for indentation. If you want to supress a line break, simply end cmlenz@820: the line with a backslash: cmlenz@820: cmlenz@820: .. code-block:: genshitext cmlenz@820: cmlenz@820: {% for item in items %}\ cmlenz@820: {% if item.visible %}\ cmlenz@820: ${item} cmlenz@820: {% end %}\ cmlenz@820: {% end %}\ cmlenz@820: cmlenz@820: Now there would be no empty lines between the items in the output. But you still cmlenz@820: get the spaces used for indentation, and because the line breaks are removed, cmlenz@820: they actually continue and add up between lines. There are numerous ways to cmlenz@820: control white-space in the output while keeping the template readable, such as cmlenz@820: moving the indentation into the delimiters, or moving the end delimiter on the cmlenz@820: next line, and so on. cmlenz@820: cmlenz@820: cmlenz@241: .. _comments: cmlenz@241: cmlenz@241: -------- cmlenz@241: Comments cmlenz@241: -------- cmlenz@241: cmlenz@820: Parts in templates can be commented out using the delimiters ``{# ... #}``. cmlenz@820: Any content in comments are removed from the output. cmlenz@820: cmlenz@820: .. code-block:: genshitext cmlenz@820: cmlenz@820: {# This won't end up in the output #} cmlenz@820: This will. cmlenz@820: cmlenz@820: Just like directive delimiters, these can be escaped by prefixing with a cmlenz@241: backslash. cmlenz@820: cmlenz@820: .. code-block:: genshitext cmlenz@820: cmlenz@820: \{# This *will* end up in the output, including delimiters #} cmlenz@820: This too. cmlenz@820: cmlenz@820: cmlenz@820: .. _legacy: cmlenz@820: cmlenz@820: --------------------------- cmlenz@820: Legacy Text Template Syntax cmlenz@820: --------------------------- cmlenz@820: cmlenz@820: The syntax for text templates was redesigned in version 0.5 of Genshi to make cmlenz@820: the language more flexible and powerful. The older syntax is based on line cmlenz@820: starting with dollar signs, similar to e.g. Cheetah_ or Velocity_. cmlenz@820: cmlenz@820: .. _cheetah: http://cheetahtemplate.org/ cmlenz@820: .. _velocity: http://jakarta.apache.org/velocity/ cmlenz@820: cmlenz@820: A simple template using the old syntax looked like this: cmlenz@820: cmlenz@820: .. code-block:: genshitext cmlenz@820: cmlenz@820: Dear $name, cmlenz@820: cmlenz@820: We have the following items for you: cmlenz@820: #for item in items cmlenz@820: * $item cmlenz@820: #end cmlenz@820: cmlenz@820: All the best, cmlenz@820: Foobar cmlenz@820: cmlenz@820: Beyond the requirement of putting directives on separate lines prefixed with cmlenz@820: dollar signs, the language itself is very similar to the new one. Except that cmlenz@820: comments are lines that start with two ``#`` characters, and a line-break at the cmlenz@820: end of a directive is removed automatically. cmlenz@820: cmlenz@820: .. note:: If you're using this old syntax, it is strongly recommended to cmlenz@820: migrate to the new syntax. Simply replace any references to cmlenz@820: ``TextTemplate`` by ``NewTextTemplate`` (and also change the cmlenz@820: text templates, of course). On the other hand, if you want to stick cmlenz@820: with the old syntax for a while longer, replace references to cmlenz@820: ``TextTemplate`` by ``OldTextTemplate``; while ``TextTemplate`` is cmlenz@820: still an alias for the old language at this point, that will change cmlenz@820: in a future release. But also note that the old syntax may be cmlenz@820: dropped entirely in a future release.