1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
|
.py Template Modules
====================
This chapter examines the structure of a .py template module. The
following few chapters will then show how each placeholder and
directive affects the generated Python code.
An example
----------
Our first template follows a long noble tradition in computer
tutorials. It produces a familiar, friendly greeting. Here's the
template:
::
Hello, world!
... the output:
::
Hello, world!
... and the .py template module cheetah-compile produced, with line
numbers added:
::
1 #!/usr/bin/env python
2 """
3 Autogenerated by CHEETAH: The Python-Powered Template Engine
4 CHEETAH VERSION: 0.9.12
5 Generation time: Sat Apr 20 14:27:47 2002
6 Source file: x.tmpl
7 Source file last modified: Wed Apr 17 22:10:59 2002
8 """
9 __CHEETAH_genTime__ = 'Sat Apr 20 14:27:47 2002'
10 __CHEETAH_src__ = 'x.tmpl'
11 __CHEETAH_version__ = '0.9.12'
12 ##################################################
13 ## DEPENDENCIES
14 import sys
15 import os
16 import os.path
17 from os.path import getmtime, exists
18 import time
19 import types
20 from Cheetah.Template import Template
21 from Cheetah.DummyTransaction import DummyTransaction
22 from Cheetah.NameMapper import NotFound, valueForName,
valueFromSearchList
23 import Cheetah.Filters as Filters
24 import Cheetah.ErrorCatchers as ErrorCatchers
25 ##################################################
26 ## MODULE CONSTANTS
27 try:
28 True, False
29 except NameError:
30 True, False = (1==1), (1==0)
31 ##################################################
32 ## CLASSES
33 class x(Template):
34 """
35
36 Autogenerated by CHEETAH: The Python-Powered Template Engine
37 """
::
38 ##################################################
39 ## GENERATED METHODS
40 def __init__(self, *args, **KWs):
41 """
42
43 """
44 Template.__init__(self, *args, **KWs)
45 self._filePath = 'x.tmpl'
46 self._fileMtime = 1019106659
47 def respond(self,
48 trans=None,
49 dummyTrans=False,
50 VFS=valueFromSearchList,
51 VFN=valueForName,
52 getmtime=getmtime,
53 currentTime=time.time):
54 """
55 This is the main method generated by Cheetah
56 """
57 if not trans:
58 trans = DummyTransaction()
59 dummyTrans = True
60 write = trans.response().write
61 SL = self._searchList
62 filter = self._currentFilter
63 globalSetVars = self._globalSetVars
64
65 ########################################
66 ## START - generated method body
67
68 if exists(self._filePath) and getmtime(self._filePath) > \
self._fileMtime:
69 self.compile(file=self._filePath)
70 write(getattr(self, self._mainCheetahMethod_for_x)
(trans=trans))
71 if dummyTrans:
72 return trans.response().getvalue()
73 else:
74 return ""
75 write('Hello, world!\n')
76
77 ########################################
78 ## END - generated method body
79
80 if dummyTrans:
81 return trans.response().getvalue()
82 else:
83 return ""
::
84
85 ##################################################
86 ## GENERATED ATTRIBUTES
87 __str__ = respond
88 _mainCheetahMethod_for_x= 'respond'
89 # CHEETAH was developed by Tavis Rudd, Chuck Esterbrook, Ian Bicking
# and Mike Orr;
90 # with code, advice and input from many other volunteers.
91 # For more information visit https://cheetahtemplate.org/
92 ##################################################
93 ## if run from command line:
94 if __name__ == '__main__':
95 x().runAsMainProgram()
(I added the line numbers for this Guide, and split a few lines to
fit the page width. The continuation lines don't have line numbers,
and I added indentation, backslashes and '#' as necessary to make
the result a valid Python program.)
The examples were generated from CVS versions of Cheetah between
0.9.12 and 0.9.14.
A walk through the example
--------------------------
Lines 20-24 are the Cheetah-specific imports. Line 33 introduces
our generated class, {x}, a subclass of {Template}. It's called x
because the source file was x.tmpl.
Lines 40-46 are the {.\_\_init\_\_} method called when the template
is instantiated or used as a Webware servlet, or when the module is
run as a standalone program. We can see it calling its superclass
constructor and setting {.\_filePath} and {.\_fileMtime} to the
filename and modification time (in Unix ticks) of the source .tmpl
file.
Lines 47-84 are the main method {.respond}, the one that fills the
template. Normally you call it without arguments, but Webware calls
it with a Webware {Transaction} object representing the current
request. Lines 57-59 set up the {trans} variable. If a real or
dummy transaction is passed in, the method uses it. Otherwise (if
the {trans} argument is {None}), the method creates a
{DummyTransaction} instance. {dummyTrans} is a flag that just tells
whether a dummy transaction is in effect; it'll be used at the end
of the method.
The other four {.respond} arguments aren't anything you'd ever want
to pass in; they exist solely to speed up access to these
frequently-used global functions. This is a standard Python trick
described in question 4.7 of the Python FAQ
(http://www.python.org/cgi-bin/faqw.py). {VFS} and {VFN} are the
functions that give your template the benefits of NameMapper
lookup, such as the ability to use the searchList.
Line 60 initializes the {write} variable. This important variable
is discussed below.
Lines 60-63 initialize a few more local variables. {SL} is the
searchList. {filter} is the current output filter. {globalSetVars}
are the variables that have been defined with {#set global}.
The comments at lines 65 and 78 delimit the start and end of the
code that varies with each template. The code outside this region
is identical in all template modules. That's not quite true -
{#import} for instance generates additional {import} statements at
the top of the module - but it's true enough for the most part.
Lines 68-74 exist only if the template source was a named file
rather than a string or file object. The stanza recompiles the
template if the source file has changed. Lines 70-74 seem to be
redundant with 75-83: both fill the template and send the output.
The reason the first set of lines exists is because the second set
may become invalid when the template is recompiled. (This is for {
re} compilation only. The initial compilation happened in the
{.\_\_init\_\_} method if the template wasn't precompiled.)
Line 75 is the most interesting line in this module. It's a direct
translation of what we put in the template definition,
"Hello, world!" Here the content is a single string literal.
{write} looks like an ordinary function call, but remember that
line 60 made it an alias to {trans.response().write}, a method in
the transaction. The next few chapters describe how the different
placeholders and directives influence this portion of the generated
class.
Lines 80-83 finish the template filling. If {trans} is a real
Webware transaction, {write} has already sent the output to Webware
for handling, so we return {""}. If {trans} is a dummy transaction,
{write} has been accumulating the output in a Python {StringIO}
object rather than sending it anywhere, so we have to return it.
Line 83 is the end of the {.respond} method.
Line 87 makes code{.\_\_str\_\_} an alias for the main method, so
that you can {print} it or apply {str} to it and it will fill the
template. Line 88 gives the name of the main method, because
sometimes it's not {.respond}.
Lines 94-95 allow the module to be run directly as a script.
Essentially, they process the command-line arguments and them make
the template fill itself.
|