logo       

Re: Modular Temptales: msg#00049

python.cheetah

Subject: Re: Modular Temptales

Alex J. Champandard wrote:

I've learnt the hard way (I should have read the guide :) that I can't reuse #def's from external templates that are #include'd. For example, I have an Interface.tmpl which would ideally use $declare_function() from another template (needed by others too).

I can think of ways around this by having a more sophisticated base Python class, but I'd like my templates to be mostly independent from the code.
Do you have any suggestions from that point of view, and how best to set up such modularity?

move you data access code / business logic to specific modules
and use the "split hierarchy approach" already suggested not too long
ago, and first reported here (i think) by peter lyons.

i've started to use it recently for a personal project (soon on-line),
i've done a couple of minor changes to original proposal, but the
concept is the same, basically:

1) wrote your servlet tree hierarchy, you known, the main SitePage.py
servlet and the subclasses.

2) wrote your cheetah templates hierarchy, possibly with a SiteTemaplate
as baseclass, so you can specify in a WYSIWYG HTML editor all the basic
elements of your page (header, footer, nav bars, etc.), also delegate
presentational details to CSS helps a lot to keep the HTML clean.

3) allow the SitePage to dinamically import a given template and
let SitePage to pass itself to that template, doing this in the
template you have access to the entire servlet fields/method.

i keep the templates and the servlets on the same folder, other
may have different setup but often a subfolder is needed to keep
things in order and having everything on the "same level" helps to
find out correct modules to load (see setTemplate method below).

here there's a portion of my SitePage.py (some code removed
for clarity):

class SitePage(Page):
"""Base site page"""

def __init__(self):
Page.__init__(self)

self._templatePath = None
self._templateDef = None

def setTemplate(self, templateDef):

# 1. context.somedir.someservlet -->
# 2. context.somedir -->
# 3. context.somedir.some_tmpl
modulePath = self.__module__.split('.')[:-1]
modulePath.append(templateDef)

self._templatePath = '.'.join(modulePath)
self._templateDef = templateDef

def awake(self, transaction):
Page.awake(self, transaction)

self.onLoad()

def onLoad(self):
"""Called at every servlet request.
Subclasses can optionally override it."""
pass

## Content methods ##

def writeHTML(self):
# do we have a template for this page? if no, use default
template = self._templateDef and self.loadTemplate() or
self.__defaultTemplate

# pass caller servlet as _ var
template._ = self
template.respond(self.transaction())

def loadTemplate(self):

module = __import__(self._templatePath, globals(), locals(),
self._templatePath)

klass = getattr(module, self._templateDef)
return klass()

## Default template ##

__defaultTemplate = Template(source='''
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN"
"http://www.w3.org/TR/html4/strict.dtd";>
<html>
<head>
<title>Blah</title>
</head>

<body>
you forgot to specify a servlet template.
</body>
</html>
''')


so a servlet of my site that inherits from
SitePage looks like this:

import blogdb # data access module
from SitePage import SitePage

class index(SitePage):
"""Show last published entry"""

def onLoad(self):
self.setTemplate('index_tmpl')

# get last published entry
self.entry = blogdb.getEntries(1, 1)[0]


setTemplate will load up "index_tmpl" file (a compiled
cheetah tmpl). index_tmpl inherits from SitePage_tmpl.html,
defined as follows:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN"
"http://www.w3.org/TR/html4/strict.dtd";>
<html>
<head>
<title>$_.title</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link href="/WK/site.css" rel="stylesheet" type="text/css">
</head>
<body>
<div id="main">
<div id="header">
<h1>deelan.com</h1>
</div>

<!-- content -->
<div id="content">
#block content
***dynamic content goes here***
#end block

<p id="copyr">Copyright &copy; 2003. Site powered by <a
href="http://www.python.org/";>Python</a> ...</p>
<!-- /content -->
</div>
<div id="sidebar">
<!-- sidebar code -->

</div>
<!-- main -->
</div>
</body>
</html>


note that "#block content" will be replaced by subclasses.
finally the index_tmpl.html looks like:

<!--
#from SitePage_tmpl import SitePage_tmpl
#extends SitePage_tmpl
-->
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN"
"http://www.w3.org/TR/html4/strict.dtd";>
<html>
<head>
<title>index_tmpl</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
<div id="content">

#def content
<h2>$_.entry.title</h2>
$_.entry.htmlContent
#end def
</div>

</body>
</html>


with "#def content" i replace "#block content" of the superclass
(SitePage_tmpl). note that it's perfectly valid for a servlet to
have one, two or more output templates, maybe the choice can be
driven by a query string / python code / POST param. also note that a
template is not forced to inherit from SitePage_tmpl, it could inherit
from a different base tmpl class (incidentaly we are moving to
a sort of model-view-controller approach).

yes, this approach force you to pre-compile all the tmpl file i usually
run a batch file), but i'm planning to tweak "loadTemplate" and allows
dinamic compiling of tmpl ...at least for subclasses.

it's not difficult to check date/time of "index_tmpl.py" against
"index_tmpl.html" and see if it needs to be recompiled. __import__
could be used when the site in published, compiling could be performed
while developing the app. but these are only ramdom thoughts. i still
have to look at the implementation details.

hope this helps.

later,
deelan


















-------------------------------------------------------
This SF.net email sponsored by: Enterprise Linux Forum Conference & Expo
The Event For Linux Datacenter Solutions & Strategies in The Enterprise Linux in the Boardroom; in the Front Office; & in the Server Room http://www.enterpriselinuxforum.com


<Prev in Thread] Current Thread [Next in Thread>
Google Custom Search

News | FAQ | advertise