Below are short HOWTOs (tutorials) on how to accomplish common tasks
in Cheetah. Feel free to add your own. See also the Tips section in
the Cheetah Users' Guide.
-- MikeOrr_ - 02 Apr 2002
---
Non-Standard Installation Process
---------------------------------
The standard setup routine didn't work for me on my Win2000 system, (I haven't bothered to setup my environment to work outside of IDLE), so here is a way to manually install Cheetah into Python 2.2 (and maybe 2.1?).
1) in your \Lib\site-packages directory, create a new directory named 'Cheetah'.
2) copy everything in the distribution's 'src' directory to your new 'Cheetah' directory.
3) move all the files in the 'src' directory that are not in a subdirectory (e.g. Tools, Tests, etc.) to the 'Cheetah' directory
That's it! If you now go to a Python command line, you should be able to successfully do a 'from Cheetah.Template import Template'
If you care to do a further test, you can go to the 'Tests' directory under 'Cheetah' and run 'Test.py' and it should be successful.
Enjoy!
ViCy_ -- 30 July 2002
---
Using Tools.SiteHierarchy
-------------------------
It took me a little while to manage to use this in a simple way so I thought I'd document what I did for posterity and save someone else some time.
What I did was create my own MenuHierarchy.py file which inherited from Hierarchy in order to customise the output methods::
class MenuHierarchy(Hierarchy):
# Add a couple of extra parameters to initialisation method
_width = 0
_bgcolor = ''
def __init__(self, hierarchy, currentURL, prefix='', menuCSSClass=None,
crumbCSSClass=None, width=0, bgcolor=""):
Hierarchy.__init__(self, hierarchy, pathToURL(currentURL), prefix, menuCSSClass, crumbCSSClass)
self._currentURL = pathToURL(currentURL)
self._width = width
self._bgcolor = bgcolor
def menuLink(self, url, text, indent):
#format specific stuff here
Note that I have added extra initialisation variables for the class
and stored away for later use in menuLink.
In my main SiteTemplate.tmpl I use the above as follows::
#attr hierarchy = [('/index.html', 'home'),
('/about.html', 'About Us'),
[('/services', 'Services'),
[('/services/products/index.html', 'Products'),
('/services/products/thimble.html', 'The Thimble'),
],
('/services/prices.html', 'Prices'),
],
('/contact.html', 'Contact Us'),
]
#set menu = MenuHierarchy($hierarchy, $self._filePath, menuCSSClass='nav', crumbCSSClass='crumb', prefix='/',
width=125, bgcolor="#CCCC99")
#echo menu.menuList()
The actual #set/#echo occurs wherever in the template is appropriate
to create the menu bar.
Notice the use of $self._filePath - I pass in the automatically
created member variable, and convert it into the name of the
associated .html file so it's all done automatically and there's no
need to do anything in the individual template file.
Anyway, hope the above is useful.
-- RobertCowham_ - 12 Aug 2002
---
Another way to do a yahoo bar
-----------------------------
I wanted just a simple yahoo bar on my site, not a multiline menu
hierarchy. I decided to hardcode the first link ("Home") since it's
on every page. In my site template I have::
#attr $crumbs = ()
Home
#for $url, $label in $crumbs
>> ${label}
#end for
Any page template subclass that wants to add elements overrides $crumbs::
#attr $crumbs = [('/writings/', 'My Writings'),
('/writings/book1/', 'This Book's Title')]
-- MikeOrr_ - 12 Aug 2002
--------
This recipe describes a way to implement WebwareSkins_ or, maybe
better, a template selection process during runtime. It is a variation
of the containment approach.
-- StephanDiehl_ - 2 Nov 2002
---
Here is a Makefile that can be dropped into the root of your context,
and build all of your templates with a simple 'make' command. It is
also set up to clean up all generated files with a 'make clean'
command. Remember to preserve tabs::
.SUFFIXES: .py .tmpl
CHEETAH = cheetah
CHEETAH_FLAGS =
TEMPLATES := $(wildcard *.tmpl */*.tmpl */*/*.tmpl */*/*/*.tmpl)
SERVLETS := $(patsubst %.tmpl, %.py, $(TEMPLATES))
PYBAK := $(patsubst %.tmpl, %.py_bak, $(TEMPLATES))
TMPLTILDE := $(patsubst %.tmpl, %.tmpl~, $(TEMPLATES))
all: $(SERVLETS)
.tmpl.py:
$(CHEETAH) compile $(CHEETAH_FLAGS) $<
clean:
rm -f $(TMPLTILDE)
rm -f $(PYBAK)
rm -f $(SERVLETS)
rm -rf *.py~ */*.py~ */*/*.py~ */*/*/*.py~
rm -rf *.pyc */*.pyc */*/*.pyc */*/*/*.pyc
-- WayneLarsen_ - 14 Feb 2002
---
Encoding with Unicode
---------------------
Here is a custom filter to encode Unicode data::
import Cheetah.Filters
class EncodeUnicode(Cheetah.Filters.Filter):
def filter(self, val, **kw):
"""Encode Unicode strings, by default in UTF-8"""
if kw.has_key('encoding'):
encoding = kw['encoding']
else:
encoding='utf8'
if type(val) == type(u''):
filtered = val.encode(encoding)
else:
filtered = str(val)
return filtered
import Cheetah.Template
t = Cheetah.Template.Template('''
$myvar
${myvar, encoding='utf16'}
''', searchList=[{'myvar': u'Asni\xe8res'}], filter=EncodeUnicode)
print t
-- RenePijlman_ - 20 Nov 2003
Integration with Apache and mod_python
--------------------------------------
Here is how I do it:
In Apache's httpd.conf::
You are
#echo self.req.get_remote_host()
which displays the remote name or IP address.
Using NameMapper_ is left as an exercice :-)
You cannot use mod_python's Publisher
(instead of my custom cheetah.py above) with most Cheetah setups. If your pages are compiled from a template, the code is in a class and the mod_python.publisher cannot find it. (If your pages are Python code, you can use http://www.modpython.org/pipermail/mod_python/2003-December/014688.html.)
A better Cheetah publisher (without exec) written by Graham Dumpleton::
from mod_python import apache
import os
# It is assumed that Apache config or .htaccess file
# blocks access to ".tmpl", ".py" and ".pyc" files.
def handler(req):
# Assume REST style URLs. Ie., no extension is used
# for accessing Cheetah pages. On this basis, first
# perform a check that there is a ".py" file in
# existance. This is done because can't distinguish
# between a non existant module and a module which has
# a coding error in it when using the function
# "apache.import_module()". By returning DECLINED,
# Apache will then serve up any static files in the
# directory which may otherwise be matched.
target = req.filename + ".py"
if not os.path.exists(target):
return apache.DECLINED
# Grab the module name to look for from the last part
# of the path. This means that pages can be spread
# across subdirectories as well.
directory,module_name = os.path.split(req.filename)
# Import the module. Any coding error in the module
# being imported is thrown back to the user. Error
# also results if by chance the target just vanished.
### module = apache.import_module(module_name,[directory]) # WRONG
module = apache.import_module(module_name,path=[directory])
# Ensure that there is a class defined in the module
# of the appropriate name.
if not hasattr(module,module_name):
return apache.DECLINED
# Create instance of the class and setup request object.
tmpl = getattr(module,module_name)()
tmpl.req = req
# Assume that HTML is being generated.
req.content_type = "text/html"
req.send_http_header()
# Now generate the actual content and return it.
req.write(tmpl.respond())
return apache.OK
The above didn't work for me.
-----------------------------
I use Debian Woody, and the packages they supply. Apache 1.3, Python 2.1, mod_python 2.7.8.
After a lot research (I thought I'd screwed up my Apache .conf, or something like
that), I started debugging, and found two problems.
1) *req.filename* had the .py extension already appended, so the script was trying *import mptest.py.py*
This may have been caused by my allowing .py, .tmpl, etc. file extensions to not be blocked. But even when I left .py off the URL, it was appended by the time req.filename was passed to the script.
The problem I kept getting when trying to access my template.py (not mptest.py!) was that the server was sending
a MIME type of 'application/x-httpd-cgi' to the browser, but what was happening was the import of my template
failed, and apache.DECLINED was getting returned. Apache was sending my script, rather the running it, in other words.
2) the call to apache.import_module() was missing the *req* parameter.
Since I had mod_python 'PythonDebug On' Apache directive in place for my script dir, I then started getting tracebacks, pointing to apache.py get_config(). Looking at the source for apache.py, I noticed that import_module call was missing the 'req' parameter. I put that in, and it all started working!
FWIW, I've here is an updated version of Graham's script, with doc strings added that other n00bs like me might find useful.::
"""Run Cheetah .tmpl/.py files via mod_python.
Provide a handler for Cheetah objects that is compatible with
mod_python calling conventions. This is required, since Cheetah objects
are organized in such as way as to prevent mod_python from finding the
proper classes and entry points; this module remedies that situation.
As an additional benefit, using this module allows Cheetah objects to
be called without the .py extension, so that URLs look 'ReST'-ful.
Imports:
mod_python.apache - objects to interface with Apache Request, etc.,
objects.
os - Python-supplied interface to the operating system.
Exports:
handler - the entry point required by mod_python for invoking an
object as a request handler.
Credits:
This code courtesy of Graham Dumpleton