Edgewall Software

Changes between Version 27 and Version 28 of MarkupTemplates


Ignore:
Timestamp:
Aug 15, 2006, 5:37:17 PM (18 years ago)
Author:
cmlenz
Comment:

Replaced section about context data with overview of Python API

Legend:

Unmodified
Added
Removed
Modified
  • MarkupTemplates

    v27 v28  
    33The most important feature provided by the Markup package is a template engine.
    44
    5 Templates are XML files of some kind (such as XHTML) that include ''[wiki:MarkupTemplates#TemplateDirectives processing directives]'' (elements or attributes identified by a separate namespace) that affect how the template is rendered, and ''[wiki:MarkupTemplates#TemplateExpressions template expressions]'' that are dynamically substituted by variable data.
     5Templates are XML files of some kind (such as XHTML) that include ''[MarkupTemplates#TemplateDirectives processing directives]'' (elements or attributes identified by a separate namespace) that affect how the template is rendered, and ''[MarkupTemplates#TemplateExpressions template expressions]'' that are dynamically substituted by variable data.
    66
    77This documentation is a work in progress and as of yet rather incomplete.
     
    1111[[PageOutline(2-3, Table of Contents, inline)]]
    1212
    13 == Template Context ==
    14 
    15 Rendering a template boils down to applying one or more template files to some input data. This input data is represented as a [wiki:ApiDocs/MarkupTemplate#markup.template:Context Context] object in Markup. A context is basically a stack of dictionaries that manages the namespace scopes during processing: for example, some variable may be available under a given name inside a loop, but not outside of that loop.
    16 
    17 Regardless of its stack behavior during templating processing, a context is usually initialized from a single dictionary:
    18 
    19 {{{
    20 >>> from markup.template import Context
    21 >>> ctxt = Context(title='Hello, world!')
    22 >>> print ctxt
    23 [{'title': 'Hello, world!'}]
    24 }}}
    25 
    26 This data is then made available for use inside the template:
    27 
    28 {{{
    29 >>> from markup.template import Template
    30 >>> tmpl = Template('<h1>$title</h1>')
    31 >>> print tmpl.generate(ctxt)
     13== Python API ==
     14
     15The Python code required for templating with Markup is generally based on the following pattern:
     16
     17 * Attain a `Template` object from a string or file object containing the template XML source. This can either be done directly, or through a `TemplateLoader` instance.
     18 * Call the `generate()` method of the template, passing any data that should be made available to the template as keyword arguments.
     19 * Serialize the resulting [MarkupStream stream] using its `render()` method.
     20
     21For example:
     22
     23{{{
     24#!python
     25from markup.template import Template
     26
     27tmpl = Template('<h1>$title</h1>')
     28stream = tmpl.generate(title='Hello, world!')
     29print stream.render('xhtml')
     30}}}
     31
     32That code would produce the following output:
     33
     34{{{
     35#!xml
    3236<h1>Hello, world!</h1>
    3337}}}
    3438
    35 Here the `title` variable in the context is accessed through a ''template expression'', discussed below.
     39See the [ApiDocs API docs] of the [ApiDocs/MarkupTemplate markup.template] and [ApiDocs/MarkupCore markup.core] modules for more details.
    3640
    3741== Template Expressions ==
     
    108112}}}
    109113
    110 The rationale behind the second form is that directives do not always map naturally to elements in the template. In such cases, the [wiki:MarkupTemplates#pystrip py:strip] directive can be used to strip off the unwanted element, or the directive can simply be used as an element.
     114The rationale behind the second form is that directives do not always map naturally to elements in the template. In such cases, the [MarkupTemplates#py:strip py:strip] directive can be used to strip off the unwanted element, or the directive can simply be used as an element.
    111115
    112116=== `py:content` ===
     
    459463
    460464{{{
     465#!xml
    461466<html xmlns="http://www.w3.org/1999/xhtml"
    462467      xmlns:py="http://markup.edgewall.org/"
     
    469474Include paths are relative to the filename of the template currently being processed. So if the example above was in the file "`myapp/index.html`" (relative to the template search path), the XInclude processor would look for the included file at "`myapp/base.html`". You can also use Unix-style relative paths, for example "`../base.html`" to look in the parent directory.
    470475
    471 Any content included this way is inserted into the generated output instead of the `<xi:include>` element. The included template sees the same [wiki:MarkupTemplates#TemplateContext context data]. [wiki:MarkupTemplates#py:match Match templates] and [wiki:MarkupTemplates#py:def template functions] in the included template are also available to the including template after the point it was included.
     476Any content included this way is inserted into the generated output instead of the `<xi:include>` element. The included template sees the same context data. [wiki:MarkupTemplates#py:match Match templates] and [wiki:MarkupTemplates#py:def template functions] in the included template are also available to the including template after the point it was included.
    472477
    473478By default, an error will be raised if an included file is not found. If that's not what you want, you can specify fallback content that should be used if the include fails. For example, to to make the include above fail silently, you'd write:
    474479
    475480{{{
     481#!xml
    476482  <xi:include href="base.html"><xi:fallback /></xi:include>
    477483}}}
    478484
    479485See the [http://www.w3.org/TR/xinclude/ XInclude specification] for more about fallback content. Note though that Markup currently only supports a small subset of XInclude.
     486
     487Incudes in Markup are fully dynamic: Just like normal attributes, the `href` attribute accepts [MarkupTemplates#TemplateExpressions expressions], and [MarkupTemplates#TemplateDirectives template directives] can be used on the `<xi:include />` element just as on any other element, meaning you can do things like conditional includes:
     488
     489{{{
     490#!xml
     491  <xi:include href="${name}.html" py:if="not in_popup"
     492              py:for="name in ('foo', 'bar', 'baz')" />
     493}}}
     494----
     495See also: MarkupGuide, MarkupRecipes