收录日期:2021/01/26 16:47:54 时间:2010-03-31 07:27:34 标签:python,template-engine,cherrypy,cheetah

I am working on a cherrypy+cheetah app and would like to improve the development experience.

I have everything working when I manually compile templates beforehand. (Update: This is how things work for production: precompile, don't ship *.tmpl and load templates as regular python modules.) However, during development I'd rather just load the templates every time they are referenced so that I don't need to kill and restart my application. I have a couple of issues I am facing:

  1. If I have templates inheriting from base templates, I get import errors (can't find base templates). I think I had this actually working during my experiments, but unfortunately didn't save it and now I can't make it work.
  2. Suppose I get 1. working, how do make it so that edits even in base templates get picked up without restart.

Below is my sample application that should demonstrate the problems. The directory structure is as follows:

t.py
templates/
    base.tmpl
    index.tmpl

t.py:

import sys

import cherrypy
from Cheetah.Template import Template

class T:
    def __init__(self, foo):
        self.foo = foo

    @cherrypy.expose
    def index(self):
        return Template(file='templates/index.tmpl',
                        searchList=[{'foo': self.foo}]).respond()

cherrypy.quickstart(T(sys.argv[1]))

base.tmpl:

#def body
This is the body from the base
#end def

This is the base doc

index.tmpl:

#from templates.base import base
#extends base
#def body
$base.body(self)
This is the extended body
#end def

This is from index

Run it like this:

python t.py Something

Try this:

Replace base.tmpl with:

#from Cheetah.Template import Template
#def body
  #set $base = Template(file="templates/base.tmpl") 
  $base.body()
  <br/>
This is the extended body
#end def

$body()
<br/>
This is from index

Looks like this question was kind of answered in another SO question. By using the cheetah_import function, I can write my methods like this:

@cherrypy.expose
def index(self):
    templates = cheetah_import('templates.index')
    t = getattr(getattr(templates, 'index'), 'index')(searchList=[{'foo': self.foo}])
    return t.respond()

I will also need to add an __init__.py into the templates directory. This approach also requires that Cherrypy's engine.autoreload_on setting is set to True.

To make production more efficient, I can make cheetah_import = __import__ and not replace the default __builtin__.import.