500
|
1 .. -*- mode: rst; encoding: utf-8 -*-
|
|
2
|
|
3 ========================
|
|
4 Genshi Templating Basics
|
|
5 ========================
|
|
6
|
|
7 Genshi provides a template engine that can be used for generating either
|
|
8 markup (such as HTML_ or XML_) or plain text. While both share some of the
|
|
9 syntax (and much of the underlying implementation) they are essentially
|
|
10 separate languages.
|
|
11
|
|
12 .. _html: http://www.w3.org/html/
|
|
13 .. _xml: http://www.w3.org/XML/
|
|
14
|
|
15 This document describes the common parts of the template engine and will be most
|
|
16 useful as reference to those developing Genshi templates. Templates are XML or
|
|
17 plain text files that include processing directives_ that affect how the
|
|
18 template is rendered, and template expressions_ that are dynamically substituted
|
|
19 by variable data.
|
|
20
|
|
21
|
|
22 .. contents:: Contents
|
|
23 :depth: 3
|
|
24 .. sectnum::
|
|
25
|
|
26 --------
|
|
27 Synopsis
|
|
28 --------
|
|
29
|
|
30 A Genshi *markup template* is a well-formed XML document with embedded Python
|
|
31 used for control flow and variable substitution. Markup templates should be
|
|
32 used to generate any kind of HTML or XML output, as they provide many advantages
|
|
33 over simple text-based templates (such as automatic escaping of strings).
|
|
34
|
|
35 The following illustrates a very basic Genshi markup template::
|
|
36
|
|
37 <?python
|
|
38 title = "A Genshi Template"
|
|
39 fruits = ["apple", "orange", "kiwi"]
|
|
40 ?>
|
|
41 <html xmlns:py="http://genshi.edgewall.org/">
|
|
42 <head>
|
|
43 <title py:content="title">This is replaced.</title>
|
|
44 </head>
|
|
45
|
|
46 <body>
|
|
47 <p>These are some of my favorite fruits:</p>
|
|
48 <ul>
|
|
49 <li py:for="fruit in fruits">
|
|
50 I like ${fruit}s
|
|
51 </li>
|
|
52 </ul>
|
|
53 </body>
|
|
54 </html>
|
|
55
|
|
56 This example shows:
|
|
57
|
|
58 (a) a Python code block, using a processing instruction
|
|
59 (b) the Genshi namespace declaration
|
|
60 (c) usage of templates directives (``py:content`` and ``py:for``)
|
|
61 (d) an inline Python expression (``${fruit}``).
|
|
62
|
|
63 The template would generate output similar to this::
|
|
64
|
|
65 <html>
|
|
66 <head>
|
|
67 <title>A Genshi Template</title>
|
|
68 </head>
|
|
69
|
|
70 <body>
|
|
71 <p>These are some of my favorite fruits:</p>
|
|
72 <ul>
|
|
73 <li>I like apples</li>
|
|
74 <li>I like oranges</li>
|
|
75 <li>I like kiwis</li>
|
|
76 </ul>
|
|
77 </body>
|
|
78 </html>
|
|
79
|
|
80 A *text template* is a simple plain text document that can also contain embedded
|
|
81 Python code. Text templates can be used to generate simple *non-markup* text
|
|
82 formats, such as the body of an plain text email. For example::
|
|
83
|
|
84 Dear $name,
|
|
85
|
|
86 These are some of my favorite fruits:
|
|
87 #for fruit in fruits
|
|
88 * $fruit
|
|
89 #end
|
|
90
|
|
91
|
|
92 ----------
|
|
93 Python API
|
|
94 ----------
|
|
95
|
|
96 The Python code required for templating with Genshi is generally based on the
|
|
97 following pattern:
|
|
98
|
|
99 * Attain a ``MarkupTemplate`` or ``TextTemplate`` object from a string or
|
|
100 file-like object containing the template source. This can either be done
|
|
101 directly, or through a ``TemplateLoader`` instance.
|
|
102 * Call the ``generate()`` method of the template, passing any data that should
|
|
103 be made available to the template as keyword arguments.
|
|
104 * Serialize the resulting stream using its ``render()`` method.
|
|
105
|
|
106 For example::
|
|
107
|
|
108 >>> from genshi.template import MarkupTemplate
|
|
109 >>> tmpl = MarkupTemplate('<h1>Hello, $name!</h1>')
|
|
110 >>> stream = tmpl.generate(name='world')
|
|
111 >>> print stream.render()
|
|
112 <h1>Hello, world!</h1>
|
|
113
|
|
114 Using a text template is similar::
|
|
115
|
|
116 >>> from genshi.template import TextTemplate
|
|
117 >>> tmpl = TextTemplate('Hello, $name!')
|
|
118 >>> stream = tmpl.generate(name='world')
|
|
119 >>> print stream.render()
|
|
120 Hello, world!
|
|
121
|
|
122 .. note:: See the Serialization_ section of the `Markup Streams`_ page for
|
|
123 information on configuring template output options.
|
|
124
|
|
125 .. _serialization: streams.html#serialization
|
|
126 .. _`Markup Streams`: streams.html
|
|
127
|
|
128 Using a template loader provides the advantage that “compiled” templates are
|
|
129 automatically cached, and only parsed again when the template file changes. In
|
|
130 addition, it enables the use of a *template search path*, allowing template
|
|
131 directories to be spread across different file-system locations. Using a
|
|
132 template loader would generally look as follows::
|
|
133
|
|
134 from genshi.template import TemplateLoader
|
|
135 loader = TemplateLoader([templates_dir1, templates_dir2])
|
|
136 tmpl = loader.load('test.html')
|
|
137 stream = tmpl.generate(title='Hello, world!')
|
|
138 print stream.render()
|
|
139
|
|
140 See the `API documentation <api/index.html>`_ for details on using Genshi via
|
|
141 the Python API.
|
|
142
|
|
143
|
|
144 .. _`expressions`:
|
|
145
|
|
146 ------------------------------------
|
|
147 Template Expressions and Code Blocks
|
|
148 ------------------------------------
|
|
149
|
|
150 Python_ expressions can be used in text and directive arguments. An expression
|
|
151 is substituted with the result of its evaluation against the template data.
|
|
152 Expressions in text (which includes the values of non-directive attributes) need
|
|
153 to prefixed with a dollar sign (``$``) and usually enclosed in curly braces
|
|
154 (``{…}``).
|
|
155
|
|
156 .. _python: http://www.python.org/
|
|
157
|
|
158 If the expression starts with a letter and contains only letters, digits, dots,
|
|
159 and underscores, the curly braces may be omitted. In all other cases, the
|
|
160 braces are required so that the template processor knows where the expression
|
|
161 ends::
|
|
162
|
|
163 >>> from genshi.template import MarkupTemplate
|
|
164 >>> tmpl = MarkupTemplate('<em>${items[0].capitalize()} item</em>')
|
|
165 >>> print tmpl.generate(items=['first', 'second'])
|
|
166 <em>First item</em>
|
|
167
|
|
168 Expressions support the full power of Python. In addition, it is possible to
|
|
169 access items in a dictionary using “dotted notation” (i.e. as if they were
|
|
170 attributes), and vice-versa (i.e. access attributes as if they were items in a
|
|
171 dictionary)::
|
|
172
|
|
173 >>> from genshi.template import MarkupTemplate
|
|
174 >>> tmpl = MarkupTemplate('<em>${dict.foo}</em>')
|
|
175 >>> print tmpl.generate(dict={'foo': 'bar'})
|
|
176 <em>bar</em>
|
|
177
|
|
178 Because there are two ways to access either attributes or items, expressions
|
|
179 do not raise the standard ``AttributeError`` or ``IndexError`` exceptions, but
|
|
180 rather an exception of the type ``UndefinedError``. The same kind of error is
|
|
181 raised when you try to use a top-level variable that is not in the context data.
|
|
182 See `Error Handling`_ below for details on how such errors are handled.
|
|
183
|
|
184
|
|
185 .. _`code blocks`:
|
|
186
|
|
187 Code Blocks
|
|
188 ===========
|
|
189
|
|
190 XML templates also support full Python code blocks using the ``<?python ?>``
|
|
191 processing instruction::
|
|
192
|
|
193 <div>
|
|
194 <?python
|
|
195 from genshi.builder import tag
|
|
196 def greeting(name):
|
|
197 return tag.b('Hello, %s!' % name') ?>
|
|
198 ${greeting('world')}
|
|
199 </div>
|
|
200
|
|
201 This will produce the following output::
|
|
202
|
|
203 <div>
|
|
204 <b>Hello, world!</b>
|
|
205 </div>
|
|
206
|
|
207 Code blocks can import modules, define classes and functions, and basically do
|
|
208 anything you can do in normal Python code. What code blocks can *not* do is to
|
|
209 produce content that is included directly in the generated page.
|
|
210
|
|
211 .. note:: Using the ``print`` statement will print to the standard output
|
|
212 stream, just as it does for other Python code in your application.
|
|
213
|
|
214 Unlike expressions, Python code in ``<?python ?>`` processing instructions can
|
|
215 not use item and attribute access in an interchangeable manner. That means that
|
|
216 “dotted notation” is always attribute access, and vice-versa.
|
|
217
|
|
218 The support for Python code blocks in templates is not supposed to encourage
|
|
219 mixing application code into templates, which is generally considered bad
|
|
220 design. If you're using many code blocks, that may be a sign that you should
|
|
221 move such code into separate Python modules.
|
|
222
|
|
223 .. note:: Code blocks are not currently supported in text templates.
|
|
224
|
|
225
|
|
226 .. _`error handling`:
|
|
227
|
|
228 Error Handling
|
|
229 ==============
|
|
230
|
|
231 By default, Genshi allows you to access variables that are not defined, without
|
|
232 raising a ``NameError`` exception as regular Python code would::
|
|
233
|
|
234 >>> from genshi.template import MarkupTemplate
|
|
235 >>> tmpl = MarkupTemplate('<p>${doh}</p>')
|
|
236 >>> print tmpl.generate().render('xhtml')
|
|
237 <p></p>
|
|
238
|
|
239 You *will* however get an exception if you try to call an undefined variable, or
|
|
240 do anything else with it, such as accessing its attributes::
|
|
241
|
|
242 >>> from genshi.template import MarkupTemplate
|
|
243 >>> tmpl = MarkupTemplate('<p>${doh.oops}</p>')
|
|
244 >>> print tmpl.generate().render('xhtml')
|
|
245 Traceback (most recent call last):
|
|
246 ...
|
|
247 UndefinedError: "doh" not defined
|
|
248
|
|
249 If you need to know whether a variable is defined, you can check its type
|
|
250 against the ``Undefined`` class, for example in a conditional directive::
|
|
251
|
|
252 >>> from genshi.template import MarkupTemplate
|
|
253 >>> tmpl = MarkupTemplate('<p>${type(doh) is not Undefined}</p>')
|
|
254 >>> print tmpl.generate().render('xhtml')
|
|
255 <p>False</p>
|
|
256
|
|
257 Alternatively, the built-in functions defined_ or value_of_ can be used in this
|
|
258 case.
|
|
259
|
|
260 Strict Mode
|
|
261 -----------
|
|
262
|
|
263 In addition to the default "lenient" error handling, Genshi lets you use a less
|
|
264 forgiving mode if you prefer errors blowing up loudly instead of being ignored
|
|
265 silently.
|
|
266
|
|
267 This mode can be chosen by passing the ``lookup='strict'`` keyword argument to
|
|
268 the template initializer, or by passing the ``variable_lookup='strict'`` keyword
|
|
269 argument to the ``TemplateLoader`` initializer::
|
|
270
|
|
271 >>> from genshi.template import MarkupTemplate
|
|
272 >>> tmpl = MarkupTemplate('<p>${doh}</p>', lookup='strict')
|
|
273 >>> print tmpl.generate().render('xhtml')
|
|
274 Traceback (most recent call last):
|
|
275 ...
|
|
276 UndefinedError: "doh" not defined
|
|
277
|
|
278 When using strict mode, any reference to an undefined variable, as well as
|
|
279 trying to access an non-existing item or attribute of an object, will cause an
|
|
280 ``UndefinedError`` to be raised immediately.
|
|
281
|
|
282 .. note:: While this mode is currently not the default, it may be promoted to
|
|
283 the default in future versions of Genshi. In general, the default
|
|
284 lenient error handling mode can be considered dangerous as it silently
|
|
285 ignores typos.
|
|
286
|
|
287 Custom Modes
|
|
288 ------------
|
|
289
|
|
290 In addition to the built-in "lenient" and "strict" modes, it is also possible to
|
|
291 use a custom error handling mode. For example, you could use lenient error
|
|
292 handling in a production environment, while also logging a warning when an
|
|
293 undefined variable is referenced.
|
|
294
|
|
295 See the API documentation of the ``genshi.template.eval`` module for details.
|
|
296
|
|
297
|
|
298 Built-in Functions & Types
|
|
299 ==========================
|
|
300
|
|
301 The following functions and types are available by default in template code, in
|
|
302 addition to the standard built-ins that are available to all Python code.
|
|
303
|
|
304 .. _`defined`:
|
|
305
|
|
306 ``defined(name)``
|
|
307 -----------------
|
|
308 This function determines whether a variable of the specified name exists in
|
|
309 the context data, and returns ``True`` if it does.
|
|
310
|
|
311 .. _`value_of`:
|
|
312
|
|
313 ``value_of(name, default=None)``
|
|
314 --------------------------------
|
|
315 This function returns the value of the variable with the specified name if
|
|
316 such a variable is defined, and returns the value of the ``default``
|
|
317 parameter if no such variable is defined.
|
|
318
|
|
319 .. _`Markup`:
|
|
320
|
|
321 ``Markup(text)``
|
|
322 ----------------
|
|
323 The ``Markup`` type marks a given string as being safe for inclusion in markup,
|
|
324 meaning it will *not* be escaped in the serialization stage. Use this with care,
|
|
325 as not escaping a user-provided string may allow malicious users to open your
|
|
326 web site to cross-site scripting attacks.
|
|
327
|
|
328 .. _`Undefined`:
|
|
329
|
|
330 ``Undefined``
|
|
331 ----------------
|
|
332 The ``Undefined`` type can be used to check whether a reference variable is
|
|
333 defined, as explained in `error handling`_.
|
|
334
|
|
335
|
|
336 .. _`directives`:
|
|
337
|
|
338 -------------------
|
|
339 Template Directives
|
|
340 -------------------
|
|
341
|
|
342 Directives provide control flow functionality for templates, such as conditions
|
|
343 or iteration. As the syntax for directives depends on whether you're using
|
|
344 markup or text templates, refer to the
|
|
345 `XML Template Language <xml-templates.html>`_ or
|
|
346 `Text Template Language <text-templates.html>`_ pages for information.
|