Dear Sam, here is a copy of my cheetahPages file to look at. To use it in a servlet I usually write my servlets like this:
from cheetahPages import cheetahPage class servlet(cheetahPage): def writeTemplate(self): self.write(self.cheetahTemplate('template.html').render()) My cheetahPages files does a couple of things for me. First it creates a cheetahTemplate object which takes care pasisng the correct searchList to the template, which is usually passed to render as an argument. The cheetahPage class does all the real work. It takes a template (which can be named anything you want, I always use .html instead of the conventional .tmpl because Dreamweaver deals with it easier) and compiles the template into a compiled template and loads the template. If the template is already compiled, it checks the date of the compiled template against template file and recompiles if needed (this is a little weak, because my original code, commented out, was compiling too often), and reloads the compiled template if needed. Like I said this is only one way to use cheetah, but it really works well for me. You'll notice the templateRoot function. This returns the relative location of the templates folder (assumed to be the same as the servlet if it si not overwritten). If templateRoot is present it looks there for the template files, this helps keep all my templates in one nice little package again separate from my servlets. Hope this helps. Jose > -------- Original Message -------- > Subject: Re: [Webware-discuss] several questions about webware > From: "Sam Nilsson" <[EMAIL PROTECTED]> > Date: Mon, January 31, 2005 12:24 am > To: "jose" <[EMAIL PROTECTED]> > > jose wrote: > > I find that this keeps my presentation code > > nicely separated from my program code, and keeps the templates very clean. > > I would be happy to share my cheetahPage with anyone if there is interest. > > > > Jose > > Hi Jose, > > I would appreciate taking a look at your cheetahPage! > > - Sam Nilsson
from WebKit.Page import Page from Cheetah.CheetahWrapper import CheetahWrapper import os, re, time __Version__ = 1.1 __Author__ = 'Jose Galvez, MD' class cheetahTemplate: ''' Cheetah Template object The purpose of this class to represent a cheetah template. Once the template is created the object has a single method, render which takes as an optional argument the searchList and returns the rendered html This class it very tightly inigrated with cheetahPage @author: Jose Galvez ''' def __init__(self, base, mod): ''' cheetahTemplate constructor @param base: The parent or base object, used as the base searchList @param mod: The compiled cheetah module as returned by cheetahPage._loadTemplate ''' self.base = base self.modName = mod.__name__.split('.').pop() self.mod = getattr(mod, self.modName) def render(self, searchList=False): ''' The only exposed method that a template may have @param searchList: Optional paramiter, the searchList is used by cheetah to find varaibles for substitution @return: rendered html as string ''' tmpl = self.mod() # now deal with the search list # did we supply a search list? if so deal with it, if not pass # an empty one if not searchList: searchList = [] else: if type(searchList) == tuple: searchList = list(searchList) elif type(searchList) == dict: searchList = [searchList] elif type(searchList) == str: raise 'Can not pass a string as a searchList, try using Vars() to accomplish this' searchList.append(self.base) # searchList manipulation to move the various parts around # so that they are searched in the correct order # dump original searchList into a holding pen using pop to emply # out the searchList orgSl = [] for i in range(len(tmpl.searchList())): orgSl.append(tmpl.searchList().pop(0)) # add our own stuff the searchList tmpl.searchList().extend(searchList) # add the original searchList to the end of the list tmpl.searchList().extend(orgSl) # end searchList manipulation #return the compiled template return tmpl.respond() class cheetahPage(Page): ''' site page for cheetah templates 1. compileTemplate(string) compile the template if it has changed since the last time it was compiled and return a cheetahTemplate object 2. Important to note that basetemplates are not reloaded very effeciantly, this is a limitation of webware not cheetah ''' def __init__(self): Page.__init__(self) # Init the cheetah cache object self.dependancyCheck = re.compile('#from (.*) import (?P<dependancy>.*)') self.cheetahCache = {} self.reloadList = [] def _respond(self, transaction): """ Handles actions if an _action_ field is defined, otherwise invokes writeHTML(). Invoked by both respondToGet() and respondToPost(). """ req = transaction.request() # Check for actions for action in self.actions(): # note the added new action do_ taken form java stuff if ((req.queryString().find('do_%s' % action) != -1) or (req.queryString().find('action_%s' % action) != -1) or (req.queryString().find('_action_%s' % action) != -1)): if self._actionSet().has_key(action): self.handleAction(action) return elif req.hasField('do_%s' % action): if self._actionSet().has_key(action): self.handleAction(action) return elif req.hasField('_action_%s' % action) or \ req.field('_action_', None) == action or \ (req.hasField('_action_%s.x' % action) and \ req.hasField('_action_%s.y' % action)): if self._actionSet().has_key(action): self.handleAction(action) return self.writeHTML() def hr(self, length = 90): ''' writes a line on a web page set at 90% xhtml complient now ''' self.writeln('<hr width="%s" />' % (str(length) + '%',)) def br(self): ''' writes a <BR> tag xhtml complient now ''' self.writeln('<BR />') def preAction(self, actionName): ''' preAction is not needed any longer ''' pass def postAction(self, actionName): ''' postAction is not needed any longer ''' pass def writeHTML(self): ''' divert the writeHTML from writeContent to writeTemplate my personal choice this can easily be changed back to something else or removed entilry ''' self.writeTemplate() def writeTemplate(self): ''' default page content, this methode needs to be overwritten to produce the default page content ''' self.writeln('Sorry this page does not have any default Content') def templateRoot(self): ''' Defines the template root for a site if you need to this is generally done best in a "site.py" page for general importation If not overwritten it will be assumed that the template root is at the same level as the servlet. Return string template root, this should be either a relative location to the servlets, or an absolute location ''' return 0 def cheetahTemplate(self, template, g=False): ''' 1. compiles a tempalte and returns a compiled template object 2. optionally provide the global namespace otherwise an error will be generated ''' self._compileTemplate(template) modName = os.path.splitext(template)[0] mod = self._loadTemplate(modName, g=g) chT = cheetahTemplate(self, mod) return chT def _loadTemplate(self, template, g=False): ''' Loads a given module as well as handeling whether the template modules needs to be reloaded @param tempalte: name of the compiled template @type template: string @parm g: globals - Globals must be passed to the function to ensure that the template is loaded into the correct namespace @type g: globals dict ''' if not g: # lets try to make up my own globals variable, this might break in # the next version of python, if so I'll have to figure something else out try: g = {'__name__':self.__module__} except: raise 'You must pass globals() to the loadTemplate function for it to work' if self.templateRoot(): mod = __import__(self.templateRoot()+'.'+template, g, {}, [template]) else: mod = __import__(template, g, {}, [template]) self._reloadTemplate(mod) return mod def _templatePath(self, t): ''' internal method used by template to get and deal with template root paths uses templateRoot to define template locations if defined @param t: template file @type: string @return: fullTemplatePath - full path to template file @return: templateName - name of compiled template ''' # First get cheetah root if self.templateRoot(): # Template paths must be relative to the servlet # using them otherwise return an error # first lets figure out what the real location of the template root is chRoot = self.serverSidePath(self.templateRoot()) if not os.path.exists(chRoot): # the relative path does not exsist raise 'Sorry the path %s does not exsist' % chRoot fullTemplatePath = os.path.join(chRoot, t) else: fullTemplatePath = self.serverSidePath(t) templateName, templateExt = os.path.splitext(t) return fullTemplatePath, templateName, templateExt[1:] def _reloadTemplate(self, mod): ''' reloads a compiled template if it marked for reloading ''' reload(mod) modName = mod.__name__.split('.').pop() if modName in self.reloadList: self.reloadList.remove(modName) reload(mod) def _compileTemplate(self, t): ''' compiles the given template into a compiled template Only compiles template if it has changed otherise it leaves it along @param t: template @type t: string ''' # compile only if we need too fullTemplatePath, templateName, templateExt = self._templatePath(t) fullCompiledTemplatePath = os.path.splitext(fullTemplatePath)[0]+'.py' mtime = os.path.getmtime(fullTemplatePath) cachedMtime = self.cheetahCache.get(templateName, False) fullCompiledTemplatePathExists = os.path.exists(fullCompiledTemplatePath) if ((fullCompiledTemplatePathExists) and (not cachedMtime) and (not self.application().server().config()['AutoReload'])): # if the compiled template exsits and we just don't have a record of it in our # cheetahCache, then don't worry assuming AutoReload is set to 0, just add it, this assums that the compiled # tempalte is actaully the correct one, if this is not correct delete it # and let the system rebuild it form scratch self.cheetahCache[templateName] = mtime elif ((mtime != cachedMtime) or (not fullCompiledTemplatePathExists)): # check to make sure __init__ exsists if not os.path.exists(os.path.join(os.path.dirname(fullTemplatePath), '__init__.py')): initFile = file(os.path.join(os.path.dirname(fullTemplatePath), '__init__.py'), 'w') initFile.write('# __init__ #') initFile.close() # open template and see if there any any dependancies that we need to compile first tmpl = file(fullTemplatePath) tLn = tmpl.readline() while tLn[0] == '#': # for l in range(10): #read only first 10 line #tLn = tmpl.readline() dependanceCheck = self.dependancyCheck.match(tLn) if dependanceCheck: dependancy = dependanceCheck.groupdict().get('dependancy', False) if dependancy: # we may be loading something that we don't have to compile try: self._compileTemplate(dependancy+'.'+templateExt) except: # nothing to do I just don't want an error to be raised pass tLn = tmpl.readline() tmpl.close() # insert the mtime into the template cache self.cheetahCache[templateName] = mtime # insert the template in to the reload variable self.reloadList.append(templateName) baseTemplateDir = os.path.dirname(fullTemplatePath) cheetahOptions = ['cheetahPage', 'compile', '--idir', baseTemplateDir, '--odir', baseTemplateDir, '--iext', templateExt, '--nobackup', templateName] # actually compile the template CheetahWrapper().main(cheetahOptions)