Mercurial > genshi > mirror
comparison doc/templates.txt @ 442:97544725bb7f trunk
Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
author | cmlenz |
---|---|
date | Thu, 12 Apr 2007 22:40:49 +0000 |
parents | |
children | ec7890aa7c0b |
comparison
equal
deleted
inserted
replaced
441:2755b06148b3 | 442:97544725bb7f |
---|---|
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 A *text template* is a simple plain text document that can also contain embedded | |
64 Python code. Text templates can be used to generate simple *non-markup* text | |
65 formats, such as the body of an plain text email. For example:: | |
66 | |
67 Dear $name, | |
68 | |
69 These are some of my favorite fruits: | |
70 #for fruit in fruits | |
71 * $fruit | |
72 #end | |
73 | |
74 | |
75 ---------- | |
76 Python API | |
77 ---------- | |
78 | |
79 The Python code required for templating with Genshi is generally based on the | |
80 following pattern: | |
81 | |
82 * Attain a ``MarkupTemplate`` or ``TextTemplate`` object from a string or | |
83 file-like object containing the template source. This can either be done | |
84 directly, or through a ``TemplateLoader`` instance. | |
85 * Call the ``generate()`` method of the template, passing any data that should | |
86 be made available to the template as keyword arguments. | |
87 * Serialize the resulting stream using its ``render()`` method. | |
88 | |
89 For example:: | |
90 | |
91 >>> from genshi.template import MarkupTemplate | |
92 >>> tmpl = MarkupTemplate('<h1>Hello, $name!</h1>') | |
93 >>> stream = tmpl.generate(name='world') | |
94 >>> print stream.render() | |
95 <h1>Hello, world!</h1> | |
96 | |
97 Using a text template is similar:: | |
98 | |
99 >>> from genshi.template import TextTemplate | |
100 >>> tmpl = TextTemplate('Hello, $name!') | |
101 >>> stream = tmpl.generate(name='world') | |
102 >>> print stream.render() | |
103 Hello, world! | |
104 | |
105 .. note:: See the Serialization_ section of the `Markup Streams`_ page for | |
106 information on configuring template output options. | |
107 | |
108 .. _serialization: streams.html#serialization | |
109 .. _`Markup Streams`: streams.html | |
110 | |
111 Using a template loader provides the advantage that “compiled” templates are | |
112 automatically cached, and only parsed again when the template file changes. In | |
113 addition, it enables the use of a *template search path*, allowing template | |
114 directories to be spread across different file-system locations. Using a | |
115 template loader would generally look as follows:: | |
116 | |
117 from genshi.template import TemplateLoader | |
118 loader = TemplateLoader([templates_dir1, templates_dir2]) | |
119 tmpl = loader.load('test.html') | |
120 stream = tmpl.generate(title='Hello, world!') | |
121 print stream.render() | |
122 | |
123 See the `API documentation <api/index.html>`_ for details on using Genshi via | |
124 the Python API. | |
125 | |
126 | |
127 .. _`expressions`: | |
128 | |
129 ------------------------------------ | |
130 Template Expressions and Code Blocks | |
131 ------------------------------------ | |
132 | |
133 Python_ expressions can be used in text and directive arguments. An expression | |
134 is substituted with the result of its evaluation against the template data. | |
135 Expressions in text (which includes the values of non-directive attributes) need | |
136 to prefixed with a dollar sign (``$``) and usually enclosed in curly braces | |
137 (``{…}``). | |
138 | |
139 .. _python: http://www.python.org/ | |
140 | |
141 If the expression starts with a letter and contains only letters, digits, dots, | |
142 and underscores, the curly braces may be omitted. In all other cases, the | |
143 braces are required so that the template processor knows where the expression | |
144 ends:: | |
145 | |
146 >>> from genshi.template import MarkupTemplate | |
147 >>> tmpl = MarkupTemplate('<em>${items[0].capitalize()} item</em>') | |
148 >>> print tmpl.generate(items=['first', 'second']) | |
149 <em>First item</em> | |
150 | |
151 Expressions support the full power of Python. In addition, it is possible to | |
152 access items in a dictionary using “dotted notation” (i.e. as if they were | |
153 attributes), and vice-versa (i.e. access attributes as if they were items in a | |
154 dictionary):: | |
155 | |
156 >>> from genshi.template import MarkupTemplate | |
157 >>> tmpl = MarkupTemplate('<em>${dict.foo}</em>') | |
158 >>> print tmpl.generate(dict={'foo': 'bar'}) | |
159 <em>bar</em> | |
160 | |
161 Because there are two ways to access either attributes or items, expressions | |
162 do not raise the standard ``AttributeError`` or ``IndexError`` exceptions, but | |
163 rather an exception of the type ``UndefinedError``. The same kind of error is | |
164 raised when you try to access a top-level variable that is not in the context | |
165 data. | |
166 | |
167 | |
168 .. _`code blocks`: | |
169 | |
170 Code Blocks | |
171 =========== | |
172 | |
173 XML templates also support full Python code blocks using the ``<?python ?>`` | |
174 processing instruction:: | |
175 | |
176 <div> | |
177 <?python | |
178 from genshi.builder import tag | |
179 def greeting(name): | |
180 return tag.b('Hello, %s!' % name') ?> | |
181 ${greeting('world')} | |
182 </div> | |
183 | |
184 This will produce the following output:: | |
185 | |
186 <div> | |
187 <b>Hello, world!</b> | |
188 </div> | |
189 | |
190 Code blocks can import modules, define classes and functions, and basically do | |
191 anything you can do in normal Python code. What code blocks can *not* do is to | |
192 produce content that is included directly in the generated page. | |
193 | |
194 .. note:: Using the ``print`` statement will print to the standard output | |
195 stream, just as it does for other Python code in your application. | |
196 | |
197 This feature is not supposed to encourage mixing application code into | |
198 templates, which is generally considered bad design. If you're using many code | |
199 blocks, that me be a sign that you should move such code into separate Python | |
200 modules. | |
201 | |
202 .. note:: Code blocks are not currently supported in text templates. | |
203 | |
204 | |
205 .. _`error handling`: | |
206 | |
207 Error Handling | |
208 ============== | |
209 | |
210 By default, Genshi allows you to access variables that are not defined, without | |
211 raising a ``NameError`` exception as regular Python code would:: | |
212 | |
213 >>> from genshi.template import MarkupTemplate | |
214 >>> tmpl = MarkupTemplate('<p>${doh}</p>') | |
215 >>> print tmpl.generate().render('xhtml') | |
216 <p></p> | |
217 | |
218 You *will* however get an exception if you try to call an undefined variable, or | |
219 do anything else with it, such as accessing its attributes:: | |
220 | |
221 >>> from genshi.template import MarkupTemplate | |
222 >>> tmpl = MarkupTemplate('<p>${doh.oops}</p>') | |
223 >>> print tmpl.generate().render('xhtml') | |
224 Traceback (most recent call last): | |
225 ... | |
226 UndefinedError: "doh" not defined | |
227 | |
228 If you need to know whether a variable is defined, you can check its type | |
229 against the ``Undefined`` class, for example in a conditional directive:: | |
230 | |
231 >>> from genshi.template import MarkupTemplate | |
232 >>> tmpl = MarkupTemplate('<p>${type(doh) is not Undefined}</p>') | |
233 >>> print tmpl.generate().render('xhtml') | |
234 <p>False</p> | |
235 | |
236 Alternatively, the built-in functions defined_ or value_of_ can be used in this | |
237 case. | |
238 | |
239 Strict Mode | |
240 ----------- | |
241 | |
242 In addition to the default "lenient" error handling, Genshi lets you use a less | |
243 forgiving mode if you prefer errors blowing up loudly instead of being ignored | |
244 silently. | |
245 | |
246 This mode can be chosen by passing the ``lookup='strict'`` keyword argument to | |
247 the template initializer, or by passing the ``variable_lookup='strict'`` keyword | |
248 argument to the ``TemplateLoader`` initializer:: | |
249 | |
250 >>> from genshi.template import MarkupTemplate | |
251 >>> tmpl = MarkupTemplate('<p>${doh}</p>', lookup='strict') | |
252 >>> print tmpl.generate().render('xhtml') | |
253 Traceback (most recent call last): | |
254 ... | |
255 UndefinedError: "doh" not defined | |
256 | |
257 When using strict mode, any reference to an undefined variable, as well as | |
258 trying to access an non-existing item or attribute of an object, will cause an | |
259 ``UndefinedError`` to be raised immediately. | |
260 | |
261 .. note:: While this mode is currently not the default, it may be promoted to | |
262 the default in future versions of Genshi. In general, the default | |
263 lenient error handling mode can be considered dangerous as it silently | |
264 ignores typos. | |
265 | |
266 Custom Modes | |
267 ------------ | |
268 | |
269 In addition to the built-in "lenient" and "strict" modes, it is also possible to | |
270 use a custom error handling mode. For example, you could use lenient error | |
271 handling in a production environment, while also logging a warning when an | |
272 undefined variable is referenced. | |
273 | |
274 See the API documentation of the ``genshi.template.eval`` module for details. | |
275 | |
276 | |
277 Built-in Functions & Types | |
278 ========================== | |
279 | |
280 The following functions and types are available by default in template code, in | |
281 addition to the standard built-ins that are available to all Python code. | |
282 | |
283 .. _`defined`: | |
284 | |
285 ``defined(name)`` | |
286 ----------------- | |
287 This function determines whether a variable of the specified name exists in | |
288 the context data, and returns ``True`` if it does. | |
289 | |
290 .. _`value_of`: | |
291 | |
292 ``value_of(name, default=None)`` | |
293 -------------------------------- | |
294 This function returns the value of the variable with the specified name if | |
295 such a variable is defined, and returns the value of the ``default`` | |
296 parameter if no such variable is defined. | |
297 | |
298 .. _`Markup`: | |
299 | |
300 ``Markup(text)`` | |
301 ---------------- | |
302 The ``Markup`` type marks a given string as being safe for inclusion in markup, | |
303 meaning it will *not* be escaped in the serialization stage. Use this with care, | |
304 as not escaping a user-provided string may allow malicious users to open your | |
305 web site to cross-site scripting attacks. | |
306 | |
307 .. _`Undefined`: | |
308 | |
309 ``Undefined`` | |
310 ---------------- | |
311 The ``Undefined`` type can be used to check whether a reference variable is | |
312 defined, as explained in `error handling`_. | |
313 | |
314 | |
315 .. _`directives`: | |
316 | |
317 ------------------- | |
318 Template Directives | |
319 ------------------- | |
320 | |
321 Directives provide control flow functionality for templates, such as conditions | |
322 or iteration. As the syntax for directives depends on whether you're using | |
323 markup or text templates, refer to the | |
324 `XML Template Language <xml-templates.html>`_ or | |
325 `Text Template Language <text-templates.html>`_ pages for information. |