~jonas-drange/ubuntu-start-page/1252899-mobile-friendly

« back to all changes in this revision

Viewing changes to src/Mako-0.1.9/doc/filtering.html

  • Committer: Matthew Nuzum
  • Date: 2008-04-18 01:58:53 UTC
  • Revision ID: matthew.nuzum@canonical.com-20080418015853-2b8rf979z2c2exxl
adding files

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<html>
 
2
<head>
 
3
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 
4
        <title>Mako Documentation - Filtering and Buffering</title>
 
5
        
 
6
    <link rel="stylesheet" href="docs.css"></link>
 
7
    <link rel="stylesheet" href="highlight.css"></link>
 
8
    
 
9
 
 
10
 
 
11
 
 
12
 
 
13
</head>
 
14
<body>
 
15
 
 
16
 
 
17
 
 
18
 
 
19
 
 
20
 
 
21
 
 
22
 
 
23
 
 
24
 
 
25
<div id="topanchor"><a name="top">&nbsp;</a></div>
 
26
 
 
27
<div id="pagecontrol"><a href="index.html">Multiple Pages</a> | <a href="documentation.html">One Page</a></div>
 
28
 
 
29
<h1>Mako Documentation</h1>
 
30
 
 
31
<div class="versionheader">Version: 0.1.9   Last Updated: 09/25/07 16:19:18</div>
 
32
 
 
33
 
 
34
 
 
35
 
 
36
 
 
37
 
 
38
 
 
39
<A name=""></a>
 
40
 
 
41
 
 
42
    <div class="topnav">
 
43
 
 
44
    
 
45
    <div class="toolbar">
 
46
        <div class="prevnext">
 
47
            Previous: <a href="inheritance.html">Inheritance</a>
 
48
 
 
49
            |
 
50
            Next: <a href="unicode.html">The Unicode Chapter</a>
 
51
        </div>
 
52
        <h3><a href="index.html">Table of Contents</a></h3>
 
53
    </div>
 
54
 
 
55
 
 
56
    <br/>
 
57
        <a href="#filtering">Filtering and Buffering</a>
 
58
        
 
59
        
 
60
    <ul>
 
61
        <li><A style="" href="filtering.html#filtering_expression">Expression Filtering</a></li>
 
62
        
 
63
            
 
64
    <ul>
 
65
        <li><A style="" href="filtering.html#filtering_expression_defaultfilters">The default_filters Argument</a></li>
 
66
        
 
67
            
 
68
    <ul>
 
69
    </ul>
 
70
 
 
71
        <li><A style="" href="filtering.html#filtering_expression_turning">Turning off Filtering with the "n" filter</a></li>
 
72
        
 
73
            
 
74
    <ul>
 
75
    </ul>
 
76
 
 
77
    </ul>
 
78
 
 
79
        <li><A style="" href="filtering.html#filtering_filtering">Filtering Defs</a></li>
 
80
        
 
81
            
 
82
    <ul>
 
83
    </ul>
 
84
 
 
85
        <li><A style="" href="filtering.html#filtering_buffering">Buffering</a></li>
 
86
        
 
87
            
 
88
    <ul>
 
89
    </ul>
 
90
 
 
91
    </ul>
 
92
 
 
93
        </div>
 
94
 
 
95
 
 
96
 
 
97
 
 
98
 
 
99
 
 
100
 
 
101
 
 
102
 
 
103
 
 
104
 
 
105
    
 
106
    <A name="filtering"></a>
 
107
    
 
108
    <div class="section">
 
109
    
 
110
 
 
111
    <h3>Filtering and Buffering</h3>
 
112
    
 
113
    
 
114
 
 
115
 
 
116
 
 
117
    
 
118
    <A name="filtering_expression"></a>
 
119
    
 
120
    <div class="subsection">
 
121
    
 
122
 
 
123
    <h3>Expression Filtering</h3>
 
124
    
 
125
    
 
126
 
 
127
<p>As described in the Syntax chapter, the "<code>|</code>" operator can be applied to a "<code>${}</code>" expression to apply escape filters to the output:
 
128
</p>
 
129
 
 
130
    
 
131
    
 
132
 
 
133
    <div class="code">
 
134
        <div class="highlight" ><pre><span class="cp">${</span><span class="s">&quot;this is some text&quot;</span> <span class="o">|</span> <span class="n">u</span><span class="cp">}</span>
 
135
</pre></div>
 
136
 
 
137
    </div>
 
138
<p>The above expression applies URL escaping to the expression, and produces <code>this+is+some+text</code>.
 
139
</p>
 
140
<p>The built-in escape flags are:
 
141
</p>
 
142
<ul>
 
143
 <li>
 
144
     <code>u</code> : URL escaping, provided by <code>urllib.quote_plus(string.encode('utf-8'))</code>
 
145
 </li>
 
146
 
 
147
 <li>
 
148
     <code>h</code> : HTML escaping, provided by <code>cgi.escape(string, True)</code>
 
149
 </li>
 
150
 
 
151
 <li>
 
152
     <code>x</code> : XML escaping
 
153
 </li>
 
154
 
 
155
 <li>
 
156
     <code>trim</code> : whitespace trimming, provided by <code>string.strip()</code>
 
157
 </li>
 
158
 
 
159
 <li>
 
160
     <code>entity</code> : produces HTML entity references for applicable strings, derived from <code>htmlentitydefs</code>
 
161
 </li>
 
162
 
 
163
 <li>
 
164
     <code>unicode</code> : produces a Python unicode string (this function is applied by default).
 
165
 </li>
 
166
 
 
167
 <li>
 
168
     <code>decode.&lt;some encoding&gt;</code> : decode input into a Python unicode with the specified encoding
 
169
 </li>
 
170
 
 
171
 <li>
 
172
     <code>n</code> : disable all default filtering; only filters specified in the local expression tag will be applied.
 
173
 </li>
 
174
</ul>
 
175
<p>To apply more than one filter, separate them by a comma:
 
176
</p>
 
177
 
 
178
    
 
179
    
 
180
 
 
181
    <div class="code">
 
182
        <div class="highlight" ><pre><span class="cp">${</span><span class="s">&quot;  &lt;tag&gt;some value&lt;/tag&gt; &quot;</span> <span class="o">|</span> <span class="n">h</span><span class="p">,</span><span class="n">trim</span><span class="cp">}</span>
 
183
</pre></div>
 
184
 
 
185
    </div>
 
186
<p>The above produces <code>&amp;lt;tag&amp;gt;some value&amp;lt;/tag&amp;gt;</code>, with no leading or trailing whitespace.  The HTML escaping function is applied first, the "trim" function second.
 
187
</p>
 
188
<p>Naturally, you can make your own filters too.  A filter is just a Python function that accepts a single string argument, and returns the filtered result.  The expressions after the <code>|</code> operator draw upon the local namespace of the template in which they appear, meaning you can define escaping functions locally:
 
189
</p>
 
190
 
 
191
    
 
192
    
 
193
 
 
194
    <div class="code">
 
195
        <div class="highlight" ><pre><span class="cp">&lt;%!</span>
 
196
    <span class="k">def</span> <span class="nf">myescape</span><span class="p">(</span><span class="n">text</span><span class="p">):</span>
 
197
        <span class="k">return</span> <span class="s">&quot;&lt;TAG&gt;&quot;</span> <span class="o">+</span> <span class="n">text</span> <span class="o">+</span> <span class="s">&quot;&lt;/TAG&gt;&quot;</span>
 
198
<span class="cp">%&gt;</span>
 
199
 
 
200
Heres some tagged text: <span class="cp">${</span><span class="s">&quot;text&quot;</span> <span class="o">|</span> <span class="n">myescape</span><span class="cp">}</span>
 
201
</pre></div>
 
202
 
 
203
    </div>
 
204
<p>Or from any Python module:
 
205
</p>
 
206
 
 
207
    
 
208
    
 
209
 
 
210
    <div class="code">
 
211
        <div class="highlight" ><pre><span class="cp">&lt;%!</span>
 
212
    <span class="k">import</span> <span class="nn">myfilters</span>
 
213
<span class="cp">%&gt;</span>
 
214
 
 
215
Heres some tagged text: <span class="cp">${</span><span class="s">&quot;text&quot;</span> <span class="o">|</span> <span class="n">myfilters</span><span class="o">.</span><span class="n">tagfilter</span><span class="cp">}</span>
 
216
</pre></div>
 
217
 
 
218
    </div>
 
219
<p>A page can apply a default set of filters to all expression tags using the <code>expression_filter</code> argument to the <code>%page</code> tag:
 
220
</p>
 
221
 
 
222
    
 
223
    
 
224
 
 
225
    <div class="code">
 
226
        <div class="highlight" ><pre><span class="cp">&lt;%</span><span class="nb">page</span> <span class="na">expression_filter=</span><span class="s">&quot;h&quot;</span><span class="cp">/&gt;</span>
 
227
 
 
228
Escaped text:  <span class="cp">${</span><span class="s">&quot;&lt;html&gt;some html&lt;/html&gt;&quot;</span><span class="cp">}</span>
 
229
</pre></div>
 
230
 
 
231
    </div>
 
232
<p>Result:
 
233
</p>
 
234
 
 
235
    
 
236
    
 
237
 
 
238
    <div class="code">
 
239
        <div class="highlight" ><pre>Escaped text: <span class="ni">&amp;lt;</span>html<span class="ni">&amp;gt;</span>some html<span class="ni">&amp;lt;</span>/html<span class="ni">&amp;gt;</span>
 
240
</pre></div>
 
241
 
 
242
    </div>
 
243
 
 
244
 
 
245
    
 
246
    <A name="filtering_expression_defaultfilters"></a>
 
247
    
 
248
    <div class="subsection">
 
249
    
 
250
 
 
251
    <h3>The default_filters Argument</h3>
 
252
    
 
253
    
 
254
 
 
255
<p><strong>New in version 0.1.2</strong>
 
256
</p>
 
257
<p>In addition to the <code>expression_filter</code> argument, the <code>default_filters</code> argument to both <code>Template</code> and <code>TemplateLookup</code> can specify filtering for all expression tags at the programmatic level.  This array-based argument defaults to <code>[&quot;unicode&quot;]</code>:
 
258
</p>
 
259
 
 
260
    
 
261
    
 
262
 
 
263
    <div class="code">
 
264
        <div class="highlight" ><pre><span class="n">t</span> <span class="o">=</span> <span class="n">TemplateLookup</span><span class="p">(</span><span class="n">directories</span><span class="o">=</span><span class="p">[</span><span class="s">&#39;/tmp&#39;</span><span class="p">],</span> <span class="n">default_filters</span><span class="o">=</span><span class="p">[</span><span class="s">&#39;unicode&#39;</span><span class="p">])</span>
 
265
</pre></div>
 
266
 
 
267
    </div>
 
268
<p>To replace the usual <code>unicode</code> function with a specific encoding, the <code>decode</code> filter can be substituted:
 
269
</p>
 
270
 
 
271
    
 
272
    
 
273
 
 
274
    <div class="code">
 
275
        <div class="highlight" ><pre><span class="n">t</span> <span class="o">=</span> <span class="n">TemplateLookup</span><span class="p">(</span><span class="n">directories</span><span class="o">=</span><span class="p">[</span><span class="s">&#39;/tmp&#39;</span><span class="p">],</span> <span class="n">default_filters</span><span class="o">=</span><span class="p">[</span><span class="s">&#39;decode.utf8&#39;</span><span class="p">])</span>
 
276
</pre></div>
 
277
 
 
278
    </div>
 
279
<p>Any string name can be added to <code>default_filters</code> where it will be added to all expressions as a filter.  The filters are applied from left to right, meaning the leftmost filter is applied first.
 
280
</p>
 
281
 
 
282
    
 
283
    
 
284
 
 
285
    <div class="code">
 
286
        <div class="highlight" ><pre><span class="n">t</span> <span class="o">=</span> <span class="n">Template</span><span class="p">(</span><span class="n">templatetext</span><span class="p">,</span> <span class="n">default_filters</span><span class="o">=</span><span class="p">[</span><span class="s">&#39;unicode&#39;</span><span class="p">,</span> <span class="s">&#39;myfilter&#39;</span><span class="p">])</span>
 
287
</pre></div>
 
288
 
 
289
    </div>
 
290
<p>To ease the usage of <code>default_filters</code> with custom filters, you can also add imports (or other code) to all templates using the <code>imports</code> argument:
 
291
</p>
 
292
 
 
293
    
 
294
    
 
295
 
 
296
    <div class="code">
 
297
        <div class="highlight" ><pre><span class="n">t</span> <span class="o">=</span> <span class="n">TemplateLookup</span><span class="p">(</span><span class="n">directories</span><span class="o">=</span><span class="p">[</span><span class="s">&#39;/tmp&#39;</span><span class="p">],</span> 
 
298
    <span class="n">default_filters</span><span class="o">=</span><span class="p">[</span><span class="s">&#39;unicode&#39;</span><span class="p">,</span> <span class="s">&#39;myfilter&#39;</span><span class="p">],</span> 
 
299
    <span class="n">imports</span><span class="o">=</span><span class="p">[</span><span class="s">&#39;from mypackage import myfilter&#39;</span><span class="p">])</span>
 
300
</pre></div>
 
301
 
 
302
    </div>
 
303
<p>The above will generate templates something like this:
 
304
</p>
 
305
 
 
306
    
 
307
    
 
308
 
 
309
    <div class="code">
 
310
        <div class="highlight" ><pre><span class="c"># ....</span>
 
311
<span class="k">from</span> <span class="nn">mypackage</span> <span class="k">import</span> <span class="n">myfilter</span>
 
312
 
 
313
<span class="k">def</span> <span class="nf">render_body</span><span class="p">(</span><span class="n">context</span><span class="p">):</span>
 
314
    <span class="n">context</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">myfilter</span><span class="p">(</span><span class="nb">unicode</span><span class="p">(</span><span class="s">&quot;some text&quot;</span><span class="p">)))</span>
 
315
</pre></div>
 
316
 
 
317
    </div>
 
318
 
 
319
 
 
320
 
 
321
            <a href="#top">back to section top</a>
 
322
    </div>
 
323
 
 
324
 
 
325
 
 
326
    
 
327
    <A name="filtering_expression_turning"></a>
 
328
    
 
329
    <div class="subsection">
 
330
    
 
331
 
 
332
    <h3>Turning off Filtering with the "n" filter</h3>
 
333
    
 
334
    
 
335
 
 
336
<p>In all cases the special <code>n</code> filter, used locally within an expression, will <strong>disable</strong> all filters declared in the <code>&lt;%page&gt;</code> tag as well <code>default_filters</code>.  Such as:
 
337
</p>
 
338
 
 
339
    
 
340
    
 
341
 
 
342
    <div class="code">
 
343
        <div class="highlight" ><pre><span class="cp">${</span><span class="s">&#39;myexpression&#39;</span> <span class="o">|</span> <span class="n">n</span><span class="cp">}</span>
 
344
</pre></div>
 
345
 
 
346
    </div>
 
347
<p>Will render <code>myexpression</code> with no filtering of any kind, and
 
348
</p>
 
349
 
 
350
    
 
351
    
 
352
 
 
353
    <div class="code">
 
354
        <div class="highlight" ><pre><span class="cp">${</span><span class="s">&#39;myexpression&#39;</span> <span class="o">|</span> <span class="n">n</span><span class="p">,</span> <span class="n">trim</span><span class="cp">}</span>
 
355
</pre></div>
 
356
 
 
357
    </div>
 
358
<p>will render <code>myexpression</code> using the <code>trim</code> filter only.  <br></br>
 
359
</p>
 
360
 
 
361
 
 
362
 
 
363
    </div>
 
364
 
 
365
 
 
366
 
 
367
 
 
368
            <a href="#top">back to section top</a>
 
369
    </div>
 
370
 
 
371
 
 
372
 
 
373
    
 
374
    <A name="filtering_filtering"></a>
 
375
    
 
376
    <div class="subsection">
 
377
    
 
378
 
 
379
    <h3>Filtering Defs</h3>
 
380
    
 
381
    
 
382
 
 
383
<p>The <code>%def</code> tag has a filter argument which will apply the given list of filter functions to the output of the <code>%def</code>:
 
384
</p>
 
385
 
 
386
    
 
387
    
 
388
 
 
389
    <div class="code">
 
390
        <div class="highlight" ><pre><span class="cp">&lt;%</span><span class="nb">def</span> <span class="na">name=</span><span class="s">&quot;foo()&quot;</span> <span class="na">filter=</span><span class="s">&quot;h, trim&quot;</span><span class="cp">&gt;</span>
 
391
    <span class="nt">&lt;b&gt;</span>this is bold<span class="nt">&lt;/b&gt;</span>
 
392
<span class="cp">&lt;/%</span><span class="nb">def</span><span class="cp">&gt;</span>
 
393
</pre></div>
 
394
 
 
395
    </div>
 
396
<p>When the filter attribute is applied to a def as above, the def is automatically <strong>buffered</strong> as well.  This is described next.
 
397
</p>
 
398
 
 
399
 
 
400
 
 
401
            <a href="#top">back to section top</a>
 
402
    </div>
 
403
 
 
404
 
 
405
 
 
406
    
 
407
    <A name="filtering_buffering"></a>
 
408
    
 
409
    <div class="subsection">
 
410
    
 
411
 
 
412
    <h3>Buffering</h3>
 
413
    
 
414
    
 
415
 
 
416
<p>One of Mako's central design goals is speed.  To this end, all of the textual content within a template and its various callables is by default piped directly to the single buffer that is stored within the <code>Context</code> object.  While this normally is easy to miss, it has certain side effects.  The main one is that when you call a def using the normal expression syntax, i.e. <code>${somedef()}</code>, it may appear that the return value of the function is the content it produced, which is then delivered to your template just like any other expression substitution, except that  normally, this is not the case; the return value of <code>${somedef()}</code> is simply the empty string <code>''</code>.  By the time you receive this empty string, the output of <code>somedef()</code> has been sent to the underlying buffer.
 
417
</p>
 
418
<p>You may not want this effect, if for example you are doing something like this:
 
419
</p>
 
420
 
 
421
    
 
422
    
 
423
 
 
424
    <div class="code">
 
425
        <div class="highlight" ><pre><span class="cp">${</span><span class="s">&quot; results &quot;</span> <span class="o">+</span> <span class="n">somedef</span><span class="p">()</span> <span class="o">+</span> <span class="s">&quot; more results &quot;</span><span class="cp">}</span>
 
426
</pre></div>
 
427
 
 
428
    </div>
 
429
<p>If the <code>somedef()</code> function produced the content "<code>somedef's results</code>", the above template would produce this output:
 
430
</p>
 
431
 
 
432
    
 
433
    
 
434
 
 
435
    <div class="code">
 
436
        <div class="highlight" ><pre>somedef&#39;s results results more results
 
437
</pre></div>
 
438
 
 
439
    </div>
 
440
<p>This is because <code>somedef()</code> fully executes before the expression returns the results of its concatenation; the concatenation in turn receives just the empty string as its middle expression.
 
441
</p>
 
442
<p>Mako provides two ways to work around this.  One is by applying buffering to the <code>%def</code> itself:
 
443
</p>
 
444
 
 
445
    
 
446
    
 
447
 
 
448
    <div class="code">
 
449
        <div class="highlight" ><pre><span class="cp">&lt;%</span><span class="nb">def</span> <span class="na">name=</span><span class="s">&quot;somedef()&quot;</span> <span class="na">buffered=</span><span class="s">&quot;true&quot;</span><span class="cp">&gt;</span>
 
450
    somedef&#39;s results
 
451
<span class="cp">&lt;/%</span><span class="nb">def</span><span class="cp">&gt;</span>
 
452
</pre></div>
 
453
 
 
454
    </div>
 
455
<p>The above definition will generate code similar to this:
 
456
</p>
 
457
 
 
458
    
 
459
    
 
460
 
 
461
    <div class="code">
 
462
        <div class="highlight" ><pre>def somedef():
 
463
    context.push_buffer()
 
464
    try:
 
465
        context.write(&quot;somedef&#39;s results&quot;)
 
466
    finally:
 
467
        buf = context.pop_buffer()
 
468
    return buf.getvalue()
 
469
</pre></div>
 
470
 
 
471
    </div>
 
472
<p>So that the content of <code>somedef()</code> is sent to a second buffer, which is then popped off the stack and its value returned.  The speed hit inherent in buffering the output of a def is also apparent.
 
473
</p>
 
474
<p>Note that the <code>filter</code> argument on %def also causes the def to be buffered.  This is so that the final content of the %def can be delivered to the escaping function in one batch, which reduces method calls and also produces more deterministic behavior for the filtering function itself, which can possibly be useful for a filtering function that wishes to apply a transformation to the text as a whole.
 
475
</p>
 
476
<p>The other way to buffer the output of a def or any Mako callable is by using the built-in <code>capture</code> function.  This function performs an operation similar to the above buffering operation except it is specified by the caller.
 
477
</p>
 
478
 
 
479
    
 
480
    
 
481
 
 
482
    <div class="code">
 
483
        <div class="highlight" ><pre><span class="cp">${</span><span class="s">&quot; results &quot;</span> <span class="o">+</span> <span class="n">capture</span><span class="p">(</span><span class="n">somedef</span><span class="p">)</span> <span class="o">+</span> <span class="s">&quot; more results &quot;</span><span class="cp">}</span>
 
484
</pre></div>
 
485
 
 
486
    </div>
 
487
<p>Note that the first argument to the <code>capture</code> function is <strong>the function itself</strong>, not the result of calling it.  This is because the <code>capture</code> function takes over the job of actually calling the target function, after setting up a buffered environment.  To send arguments to the function, just send them to <code>capture</code> instead:
 
488
</p>
 
489
 
 
490
    
 
491
    
 
492
 
 
493
    <div class="code">
 
494
        <div class="highlight" ><pre><span class="cp">${</span><span class="n">capture</span><span class="p">(</span><span class="n">somedef</span><span class="p">,</span> <span class="mi">17</span><span class="p">,</span> <span class="s">&#39;hi&#39;</span><span class="p">,</span> <span class="n">use_paging</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span><span class="cp">}</span>
 
495
</pre></div>
 
496
 
 
497
    </div>
 
498
<p>The above call is equivalent to the unbuffered call:
 
499
</p>
 
500
 
 
501
    
 
502
    
 
503
 
 
504
    <div class="code">
 
505
        <div class="highlight" ><pre><span class="cp">${</span><span class="n">somedef</span><span class="p">(</span><span class="mi">17</span><span class="p">,</span> <span class="s">&#39;hi&#39;</span><span class="p">,</span> <span class="n">use_paging</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span><span class="cp">}</span>
 
506
</pre></div>
 
507
 
 
508
    </div>
 
509
 
 
510
 
 
511
 
 
512
 
 
513
    </div>
 
514
 
 
515
 
 
516
 
 
517
 
 
518
            <a href="#top">back to section top</a>
 
519
    </div>
 
520
 
 
521
 
 
522
</html>
 
523
 
 
524
 
 
525
    <div class="toolbar">
 
526
        <div class="prevnext">
 
527
            Previous: <a href="inheritance.html">Inheritance</a>
 
528
 
 
529
            |
 
530
            Next: <a href="unicode.html">The Unicode Chapter</a>
 
531
        </div>
 
532
        <h3><a href="index.html">Table of Contents</a></h3>
 
533
    </div>
 
534
 
 
535
 
 
536
 
 
537
 
 
538
 
 
539
 
 
540
</body>
 
541
</html>
 
542
 
 
543
 
 
544
 
 
545
 
 
546