CherryPy Project Download

How to use powerful Cheetah cache mechanism with CherryPy?

Cheetah Template uses quite powerfull cache mechanism. I have just improved its features with 'varyBy' keyword argument that will allow a separate cache instances to be created for a variety of conditions, such as different query string parameters or browser types.

Look at the example. First lets upgrade two functions from Compiler.py file (found in Lib/site-libs/Cheetah/src folder) to the following code:

    def startCacheRegion(self, cacheInfo, lineCol):
        """
        Added params: varyBy, debug. 
        Author: Jarosław Zabiełło (http://zabiello.com)
        Version: 2004-11-28
        """
        ID = self.nextCacheID()
        interval = cacheInfo.get('interval',None)
        test = cacheInfo.get('test',None)
        self.__CacheRegionVaryBy = cacheInfo.get('varyBy',repr(ID))
        self.__CacheRegionDebug = cacheInfo.get('debug', False)
        self._cacheRegionOpen = True    # attrib of current methodCompiler        
        self.addChunk('## START CACHE REGION: at line, col ' + str(lineCol) + ' in the source.')
        self.addChunk('RECACHE = True')
        self.addChunk('import md5')
        self.addChunk('self._varyByHash = md5.new(str(%s)).hexdigest()' % self.__CacheRegionVaryBy)
        self.addChunk('if not self._cacheData.has_key(self._varyByHash):')
        self.indent()
        self.addChunk("self._cacheData[self._varyByHash] = {'output':None, 'refreshTime':None}")

        if cacheInfo.has_key('id'):
            self.addChunk("self._cacheIndex['%s']= self._varyByHash" % cacheInfo['id'])            

        if not (interval or test):
            self.addChunk('pass')
        if interval:
            setRefreshTime = "self._cacheData[self._varyByHash]['refreshTime'] = currentTime()  + %s"  % interval
            self.addChunk(setRefreshTime)
            self.dedent()
            self.addChunk("elif currentTime() > self._cacheData[self._varyByHash]['refreshTime']:")
            self.indent()
            self.addChunk(setRefreshTime)
            self.addMethDocString('This cache will be refreshed every %s seconds.'  % interval)
        if test:
            self.dedent()
            self.addChunk('elif ' + test + ':')
            self.indent()
            self.addChunk('RECACHE = True') 
        self.dedent()
        self.addChunk('else:')
        self.indent()
        self.addChunk('RECACHE = False')
        self.dedent()
        self.addChunk('if RECACHE:')
        self.indent()
        self.addChunk('orig_trans = trans')
        self.addChunk('trans = cacheCollector = DummyTransaction()')
        self.addChunk('write = cacheCollector.response().write')
        
    def endCacheRegion(self):
        self._cacheRegionOpen = False
        self.addChunk('trans = orig_trans')

        self.addChunk('write = trans.response().write')
        self.addChunk("self._cacheData[self._varyByHash]['output'] = cacheCollector.response().getvalue()")
        self.addChunk('del cacheCollector')
        self.dedent()
        self.addWriteChunk("self._cacheData[self._varyByHash]['output']")
        if self.__CacheRegionDebug:
            self.addWriteChunk("'<hr />%s' % self._cacheData")
        self.addChunk('## END CACHE REGION')
        self.addChunk('')

OK. Now, let's check how it works. First, create the following test files.

File: TestTemplate.html

#import cherrypy
#import time

Hello $username!

#set $_varyBy=$cherrypy.request.params.get('x')
#set $_test=$cherrypy.request.params.get('refresh')

#cache id='test', test=$_test, timer='10s', varyBy=$_varyBy, debug=True
$time.strftime('%H:%M:%S', time.localtime())
#end cache

File: Test.py

from Cheetah.Template import Template
import cherrypy

#import compiled TestTemplate:
from TestTemplate import TestTemplate

class TestCheetah(object):

   def __init__(self):
      """
      For threadPool=1 or for forks mode you can define instance 
      of Cheetah here, in constructor. 
      For threadPool > 1 it should be defined in engine.on_start_thread
      method because it have to be executed only ONCE and you must aware
      of threads conflict. on_start_thread is a good place. If you create
      instance of TestTemplate in the place where it will be executed
      for every browser request, Cheetah cache wil NOT work!
      """
      self._tmpl = TestTemplate()
      self._tmpl.username = "John Brown"      

   def index(self, **kwargs):
      return self._tmpl.respond()
   index.exposed = True

cherrypy.quickstart(TestCheetah(), conf='test.conf')

File test.conf:

[/]
server.socket_port = 8080
server.thread_pool = 1

Of course, TestTemplate.html should be compiled first. You can do do it and execute CherryPy with the following script:

python cheetah-compile.py TestTemplate.html --iext html
python Test.py

Execute, check results and have a fun! :)

Older versions

replace this with this
2.2cherrypy.quickstart(TestCheetah(), conf='test.conf')cherrypy.config.update(configFile = 'test.conf')
cherrypy.tree.mount(TestCheetah())
cpg.server.start()
2.1on_start_thread_listonStartThreadList
2.0onStartThreadList_cpInitThread()
import cherrypyfrom cherrypy import cpg as cherrypy
cherrypy.quickstart(TestCheetah(), conf='test.conf')cpg.root = TestCheetah()
cpg.server.start(configFile = 'test.conf')

test.conf for 2.0:

[server]
socketPort = 8080
threadPool = 1

Hosted by WebFaction

Log in as guest/cherrypy to create/edit wiki pages