Mercurial > genshi > mirror
comparison doc/templates.txt @ 820:9755836bb396 experimental-inline
Sync (old) experimental inline branch with trunk@1027.
author | cmlenz |
---|---|
date | Wed, 11 Mar 2009 17:51:06 +0000 |
parents | 3eb30e4ece8c |
children | fe25855324dd |
comparison
equal
deleted
inserted
replaced
500:3eb30e4ece8c | 820:9755836bb396 |
---|---|
30 A Genshi *markup template* is a well-formed XML document with embedded Python | 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 | 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 | 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). | 33 over simple text-based templates (such as automatic escaping of strings). |
34 | 34 |
35 The following illustrates a very basic Genshi markup template:: | 35 The following illustrates a very basic Genshi markup template: |
36 | |
37 .. code-block:: genshi | |
36 | 38 |
37 <?python | 39 <?python |
38 title = "A Genshi Template" | 40 title = "A Genshi Template" |
39 fruits = ["apple", "orange", "kiwi"] | 41 fruits = ["apple", "orange", "kiwi"] |
40 ?> | 42 ?> |
58 (a) a Python code block, using a processing instruction | 60 (a) a Python code block, using a processing instruction |
59 (b) the Genshi namespace declaration | 61 (b) the Genshi namespace declaration |
60 (c) usage of templates directives (``py:content`` and ``py:for``) | 62 (c) usage of templates directives (``py:content`` and ``py:for``) |
61 (d) an inline Python expression (``${fruit}``). | 63 (d) an inline Python expression (``${fruit}``). |
62 | 64 |
63 The template would generate output similar to this:: | 65 The template would generate output similar to this: |
66 | |
67 .. code-block:: genshi | |
64 | 68 |
65 <html> | 69 <html> |
66 <head> | 70 <head> |
67 <title>A Genshi Template</title> | 71 <title>A Genshi Template</title> |
68 </head> | 72 </head> |
77 </body> | 81 </body> |
78 </html> | 82 </html> |
79 | 83 |
80 A *text template* is a simple plain text document that can also contain embedded | 84 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 | 85 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:: | 86 formats, such as the body of an plain text email. For example: |
87 | |
88 .. code-block:: genshitext | |
83 | 89 |
84 Dear $name, | 90 Dear $name, |
85 | 91 |
86 These are some of my favorite fruits: | 92 These are some of my favorite fruits: |
87 #for fruit in fruits | 93 #for fruit in fruits |
101 directly, or through a ``TemplateLoader`` instance. | 107 directly, or through a ``TemplateLoader`` instance. |
102 * Call the ``generate()`` method of the template, passing any data that should | 108 * Call the ``generate()`` method of the template, passing any data that should |
103 be made available to the template as keyword arguments. | 109 be made available to the template as keyword arguments. |
104 * Serialize the resulting stream using its ``render()`` method. | 110 * Serialize the resulting stream using its ``render()`` method. |
105 | 111 |
106 For example:: | 112 For example: |
113 | |
114 .. code-block:: pycon | |
107 | 115 |
108 >>> from genshi.template import MarkupTemplate | 116 >>> from genshi.template import MarkupTemplate |
109 >>> tmpl = MarkupTemplate('<h1>Hello, $name!</h1>') | 117 >>> tmpl = MarkupTemplate('<h1>Hello, $name!</h1>') |
110 >>> stream = tmpl.generate(name='world') | 118 >>> stream = tmpl.generate(name='world') |
111 >>> print stream.render() | 119 >>> print stream.render('xhtml') |
112 <h1>Hello, world!</h1> | 120 <h1>Hello, world!</h1> |
113 | 121 |
114 Using a text template is similar:: | 122 .. note:: See the Serialization_ section of the `Markup Streams`_ page for |
123 information on configuring template output options. | |
124 | |
125 Using a text template is similar: | |
126 | |
127 .. code-block:: pycon | |
115 | 128 |
116 >>> from genshi.template import TextTemplate | 129 >>> from genshi.template import TextTemplate |
117 >>> tmpl = TextTemplate('Hello, $name!') | 130 >>> tmpl = TextTemplate('Hello, $name!') |
118 >>> stream = tmpl.generate(name='world') | 131 >>> stream = tmpl.generate(name='world') |
119 >>> print stream.render() | 132 >>> print stream |
120 Hello, world! | 133 Hello, world! |
121 | 134 |
122 .. note:: See the Serialization_ section of the `Markup Streams`_ page for | 135 .. note:: If you want to use text templates, you should consider using the |
123 information on configuring template output options. | 136 ``NewTextTemplate`` class instead of simply ``TextTemplate``. See |
137 the `Text Template Language`_ page. | |
124 | 138 |
125 .. _serialization: streams.html#serialization | 139 .. _serialization: streams.html#serialization |
140 .. _`Text Template Language`: text-templates.html | |
126 .. _`Markup Streams`: streams.html | 141 .. _`Markup Streams`: streams.html |
127 | 142 |
128 Using a template loader provides the advantage that “compiled” templates are | 143 Using a template loader provides the advantage that “compiled” templates are |
129 automatically cached, and only parsed again when the template file changes. In | 144 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 | 145 addition, it enables the use of a *template search path*, allowing template |
131 directories to be spread across different file-system locations. Using a | 146 directories to be spread across different file-system locations. Using a |
132 template loader would generally look as follows:: | 147 template loader would generally look as follows: |
148 | |
149 .. code-block:: python | |
133 | 150 |
134 from genshi.template import TemplateLoader | 151 from genshi.template import TemplateLoader |
135 loader = TemplateLoader([templates_dir1, templates_dir2]) | 152 loader = TemplateLoader([templates_dir1, templates_dir2]) |
136 tmpl = loader.load('test.html') | 153 tmpl = loader.load('test.html') |
137 stream = tmpl.generate(title='Hello, world!') | 154 stream = tmpl.generate(title='Hello, world!') |
156 .. _python: http://www.python.org/ | 173 .. _python: http://www.python.org/ |
157 | 174 |
158 If the expression starts with a letter and contains only letters, digits, dots, | 175 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 | 176 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 | 177 braces are required so that the template processor knows where the expression |
161 ends:: | 178 ends: |
179 | |
180 .. code-block:: pycon | |
162 | 181 |
163 >>> from genshi.template import MarkupTemplate | 182 >>> from genshi.template import MarkupTemplate |
164 >>> tmpl = MarkupTemplate('<em>${items[0].capitalize()} item</em>') | 183 >>> tmpl = MarkupTemplate('<em>${items[0].capitalize()} item</em>') |
165 >>> print tmpl.generate(items=['first', 'second']) | 184 >>> print tmpl.generate(items=['first', 'second']) |
166 <em>First item</em> | 185 <em>First item</em> |
167 | 186 |
168 Expressions support the full power of Python. In addition, it is possible to | 187 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 | 188 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 | 189 attributes), and vice-versa (i.e. access attributes as if they were items in a |
171 dictionary):: | 190 dictionary): |
191 | |
192 .. code-block:: pycon | |
172 | 193 |
173 >>> from genshi.template import MarkupTemplate | 194 >>> from genshi.template import MarkupTemplate |
174 >>> tmpl = MarkupTemplate('<em>${dict.foo}</em>') | 195 >>> tmpl = MarkupTemplate('<em>${dict.foo}</em>') |
175 >>> print tmpl.generate(dict={'foo': 'bar'}) | 196 >>> print tmpl.generate(dict={'foo': 'bar'}) |
176 <em>bar</em> | 197 <em>bar</em> |
180 rather an exception of the type ``UndefinedError``. The same kind of error is | 201 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. | 202 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. | 203 See `Error Handling`_ below for details on how such errors are handled. |
183 | 204 |
184 | 205 |
206 Escaping | |
207 ======== | |
208 | |
209 If you need to include a literal dollar sign in the output where Genshi would | |
210 normally detect an expression, you can simply add another dollar sign: | |
211 | |
212 .. code-block:: pycon | |
213 | |
214 >>> from genshi.template import MarkupTemplate | |
215 >>> tmpl = MarkupTemplate('<em>$foo</em>') # Wanted "$foo" as literal output | |
216 >>> print tmpl.generate() | |
217 Traceback (most recent call last): | |
218 ... | |
219 UndefinedError: "foo" not defined | |
220 >>> tmpl = MarkupTemplate('<em>$$foo</em>') | |
221 >>> print tmpl.generate() | |
222 <em>$foo</em> | |
223 | |
224 But note that this is not necessary if the characters following the dollar sign | |
225 do not qualify as an expression. For example, the following needs no escaping: | |
226 | |
227 .. code-block:: pycon | |
228 | |
229 >>> tmpl = MarkupTemplate('<script>$(function() {})</script>') | |
230 >>> print tmpl.generate() | |
231 <script>$(function() {})</script> | |
232 | |
233 On the other hand, Genshi will always replace two dollar signs in text with a | |
234 single dollar sign, so you'll need to use three dollar signs to get two in the | |
235 output: | |
236 | |
237 .. code-block:: pycon | |
238 | |
239 >>> tmpl = MarkupTemplate('<script>$$$("div")</script>') | |
240 >>> print tmpl.generate() | |
241 <script>$$("div")</script> | |
242 | |
243 | |
185 .. _`code blocks`: | 244 .. _`code blocks`: |
186 | 245 |
187 Code Blocks | 246 Code Blocks |
188 =========== | 247 =========== |
189 | 248 |
190 XML templates also support full Python code blocks using the ``<?python ?>`` | 249 Templates also support full Python code blocks, using the ``<?python ?>`` |
191 processing instruction:: | 250 processing instruction in XML templates: |
251 | |
252 .. code-block:: genshi | |
192 | 253 |
193 <div> | 254 <div> |
194 <?python | 255 <?python |
195 from genshi.builder import tag | 256 from genshi.builder import tag |
196 def greeting(name): | 257 def greeting(name): |
197 return tag.b('Hello, %s!' % name') ?> | 258 return tag.b('Hello, %s!' % name) ?> |
198 ${greeting('world')} | 259 ${greeting('world')} |
199 </div> | 260 </div> |
200 | 261 |
201 This will produce the following output:: | 262 This will produce the following output: |
263 | |
264 .. code-block:: xml | |
202 | 265 |
203 <div> | 266 <div> |
204 <b>Hello, world!</b> | 267 <b>Hello, world!</b> |
205 </div> | 268 </div> |
206 | 269 |
270 In text templates (although only those using the new syntax introduced in | |
271 Genshi 0.5), code blocks use the special ``{% python %}`` directive: | |
272 | |
273 .. code-block:: genshitext | |
274 | |
275 {% python | |
276 from genshi.builder import tag | |
277 def greeting(name): | |
278 return 'Hello, %s!' % name | |
279 %} | |
280 ${greeting('world')} | |
281 | |
282 This will produce the following output:: | |
283 | |
284 Hello, world! | |
285 | |
286 | |
207 Code blocks can import modules, define classes and functions, and basically do | 287 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 | 288 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. | 289 produce content that is emitted directly tp the generated output. |
210 | 290 |
211 .. note:: Using the ``print`` statement will print to the standard output | 291 .. note:: Using the ``print`` statement will print to the standard output |
212 stream, just as it does for other Python code in your application. | 292 stream, just as it does for other Python code in your application. |
213 | 293 |
214 Unlike expressions, Python code in ``<?python ?>`` processing instructions can | 294 Unlike expressions, Python code in ``<?python ?>`` processing instructions can |
218 The support for Python code blocks in templates is not supposed to encourage | 298 The support for Python code blocks in templates is not supposed to encourage |
219 mixing application code into templates, which is generally considered bad | 299 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 | 300 design. If you're using many code blocks, that may be a sign that you should |
221 move such code into separate Python modules. | 301 move such code into separate Python modules. |
222 | 302 |
223 .. note:: Code blocks are not currently supported in text templates. | 303 If you'd rather not allow the use of Python code blocks in templates, you can |
304 simply set the ``allow_exec`` parameter (available on the ``Template`` and the | |
305 ``TemplateLoader`` initializers) to ``False``. In that case Genshi will raise | |
306 a syntax error when a ``<?python ?>`` processing instruction is encountered. | |
307 But please note that disallowing code blocks in templates does not turn Genshi | |
308 into a sandboxable template engine; there are sufficient ways to do harm even | |
309 using plain expressions. | |
224 | 310 |
225 | 311 |
226 .. _`error handling`: | 312 .. _`error handling`: |
227 | 313 |
228 Error Handling | 314 Error Handling |
229 ============== | 315 ============== |
230 | 316 |
231 By default, Genshi allows you to access variables that are not defined, without | 317 By default, Genshi raises an ``UndefinedError`` if a template expression |
232 raising a ``NameError`` exception as regular Python code would:: | 318 attempts to access a variable that is not defined: |
319 | |
320 .. code-block:: pycon | |
233 | 321 |
234 >>> from genshi.template import MarkupTemplate | 322 >>> from genshi.template import MarkupTemplate |
235 >>> tmpl = MarkupTemplate('<p>${doh}</p>') | 323 >>> tmpl = MarkupTemplate('<p>${doh}</p>') |
324 >>> tmpl.generate().render('xhtml') | |
325 Traceback (most recent call last): | |
326 ... | |
327 UndefinedError: "doh" not defined | |
328 | |
329 You can change this behavior by setting the variable lookup mode to "lenient". | |
330 In that case, accessing undefined variables returns an `Undefined` object, | |
331 meaning that the expression does not fail immediately. See below for details. | |
332 | |
333 If you need to check whether a variable exists in the template context, use the | |
334 defined_ or the value_of_ function described below. To check for existence of | |
335 attributes on an object, or keys in a dictionary, use the ``hasattr()``, | |
336 ``getattr()`` or ``get()`` functions, or the ``in`` operator, just as you would | |
337 in regular Python code: | |
338 | |
339 >>> from genshi.template import MarkupTemplate | |
340 >>> tmpl = MarkupTemplate('<p>${defined("doh")}</p>') | |
341 >>> print tmpl.generate().render('xhtml') | |
342 <p>False</p> | |
343 | |
344 .. note:: Lenient error handling was the default in Genshi prior to version 0.5. | |
345 Strict mode was introduced in version 0.4, and became the default in | |
346 0.5. The reason for this change was that the lenient error handling | |
347 was masking actual errors in templates, thereby also making it harder | |
348 to debug some problems. | |
349 | |
350 | |
351 .. _`lenient`: | |
352 | |
353 Lenient Mode | |
354 ------------ | |
355 | |
356 If you instruct Genshi to use the lenient variable lookup mode, it allows you | |
357 to access variables that are not defined, without raising an ``UndefinedError``. | |
358 | |
359 This mode can be chosen by passing the ``lookup='lenient'`` keyword argument to | |
360 the template initializer, or by passing the ``variable_lookup='lenient'`` | |
361 keyword argument to the ``TemplateLoader`` initializer: | |
362 | |
363 .. code-block:: pycon | |
364 | |
365 >>> from genshi.template import MarkupTemplate | |
366 >>> tmpl = MarkupTemplate('<p>${doh}</p>', lookup='lenient') | |
236 >>> print tmpl.generate().render('xhtml') | 367 >>> print tmpl.generate().render('xhtml') |
237 <p></p> | 368 <p></p> |
238 | 369 |
239 You *will* however get an exception if you try to call an undefined variable, or | 370 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:: | 371 do anything else with it, such as accessing its attributes: |
241 | 372 |
242 >>> from genshi.template import MarkupTemplate | 373 .. code-block:: pycon |
243 >>> tmpl = MarkupTemplate('<p>${doh.oops}</p>') | 374 |
375 >>> from genshi.template import MarkupTemplate | |
376 >>> tmpl = MarkupTemplate('<p>${doh.oops}</p>', lookup='lenient') | |
244 >>> print tmpl.generate().render('xhtml') | 377 >>> print tmpl.generate().render('xhtml') |
245 Traceback (most recent call last): | 378 Traceback (most recent call last): |
246 ... | 379 ... |
247 UndefinedError: "doh" not defined | 380 UndefinedError: "doh" not defined |
248 | 381 |
249 If you need to know whether a variable is defined, you can check its type | 382 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:: | 383 against the ``Undefined`` class, for example in a conditional directive: |
251 | 384 |
252 >>> from genshi.template import MarkupTemplate | 385 .. code-block:: pycon |
253 >>> tmpl = MarkupTemplate('<p>${type(doh) is not Undefined}</p>') | 386 |
387 >>> from genshi.template import MarkupTemplate | |
388 >>> tmpl = MarkupTemplate('<p>${type(doh) is not Undefined}</p>', | |
389 ... lookup='lenient') | |
254 >>> print tmpl.generate().render('xhtml') | 390 >>> print tmpl.generate().render('xhtml') |
255 <p>False</p> | 391 <p>False</p> |
256 | 392 |
257 Alternatively, the built-in functions defined_ or value_of_ can be used in this | 393 Alternatively, the built-in functions defined_ or value_of_ can be used in this |
258 case. | 394 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 | 395 |
287 Custom Modes | 396 Custom Modes |
288 ------------ | 397 ------------ |
289 | 398 |
290 In addition to the built-in "lenient" and "strict" modes, it is also possible to | 399 In addition to the built-in "lenient" and "strict" modes, it is also possible to |