Warning: Can't synchronize with repository "(default)" (Unsupported version control system "svn": No module named svn). Look in the Trac log for more information.

Changes between Version 1 and Version 2 of NonPackagedKidTemplates


Ignore:
Timestamp:
08/08/06 04:02:47 (13 years ago)
Author:
robinbryce
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • NonPackagedKidTemplates

    v1 v2  
    33You want to deploy a site that uses kid templates in a manner that suites more traditional web deployment models. For example, you are working with web developers who are comfortable with html templating, possibly are familiar with kid, but are not python developers. Additionaly you may have very specific requirements with regard to how your site content is hosted, permissions, existing cacheing systems etc. For these reasons it is more convenient to support a site directory to which kid template files (.kid) can be uploaded to. The standard mechanisms for integrating kid templates with turbogears controlers look like this: 
    44{{{ 
    5     class Root(controllers.RootControllers): 
    6         @expose(template='yourpythonapp.templates.welcome') 
    7         def index(self): 
    8             import time 
    9             return dict(now=time.time()) 
     5class Root(controllers.RootControllers): 
     6    @expose(template='yourpythonapp.templates.welcome') 
     7    def index(self): 
     8        import time 
     9        return dict(now=time.time()) 
    1010}}} 
    1111 
    1212This uses the TurboKid plugin to load templates from a python package that you must provide to wrap the templates. This example enables you to rewrite the above as: 
    1313{{{ 
    14     class Root(controllers.RootControllers): 
    15         @expose(template='yourpythonapp/kid/welcome') 
    16         def index(self): 
    17             import time 
    18             return dict(now=time.time()) 
     14class Root(controllers.RootControllers): 
     15     
     16    # bigsitesupport is the name you gave your turbogears application when you set it up (tg-admin quickstart) 
     17 
     18    @expose(template='bigsitesupport/kid/welcome') 
     19    def index(self): 
     20        import time 
     21        return dict(now=time.time()) 
    1922}}} 
    2023 
    2124And have welcome.kid loaded from the file system (possibly via custom caching machinery) without the need to bundle the template in a python package. It does this using a technique that is compatible with TurboKid and the existing TurboGears template engine machinery. 
     25 
     26== The python import hook == 
     27 
     28First create an import hook that is compatible with PEP 302 [http://www.python.org/dev/peps/pep-0302/]. This enables your customisation to be picked up by TruboKid with out needing to patch its source. This example is derived from the import machinery that exists in kid.importer [http://www.kid-templating.org/trac/browser/trunk/kid/importer.py]. 
     29 
     30{{{ 
     31import os, logging 
     32from sys import path_hooks, path_importer_cache 
     33from kid.importer import import_template 
     34 
     35log = logging.getLogger('bigsitesupport.kidimport') 
     36 
     37class _Importer(object): 
     38    def __init__(self, config, path=None): 
     39        self.config = config 
     40        # assumes you have used the turbogears [/static] directory to configure the location  
     41        # of your non packaged kid templates. you could quite reasonably introduce a completely new url 
     42        # mapping for this purpose. using the existing [/static] lets you get things working with less work.  
     43        self.confstatic=config.get('/static') 
     44        self.staticdir=self.confstatic and self.confstatic.get( 
     45                'static_filter.dir', None) 
     46        self.path = path 
     47 
     48    def find_module(self, fullname): 
     49        log.info( 
     50            "CONSIDERING: fullname='%s' initpath='%s' ***" % ( 
     51                fullname,self.path)) 
     52        if not self.staticdir: 
     53            return 
     54        parts=fullname.split('/', 1) 
     55        if len(parts) != 2: 
     56            log.info("REJECTING: not a uri, [%s]" % fullname) 
     57            return 
     58        filename=os.path.join(self.staticdir, parts[1].replace('/',os.sep)) 
     59        filename+='.kid' 
     60        if not os.path.exists(filename): 
     61            log.info("REJECTING: file does not exist [%s]" % filename) 
     62            return 
     63        self._filename = filename 
     64        return self 
     65 
     66    def load_module(self, fullname): 
     67        # A production quality implementation would integrate with your custom  
     68        # caching solution in this method. This expositional implementation will 
     69        # ** force ** recompilation of the  template on every access. Which is fine  
     70        # for development but not for the real world. 
     71 
     72        return import_template(fullname, self._filename, force=1) 
     73         
     74 
     75def Importer_factory(config): 
     76    """Factory method to make turbogears config available to the hook""" 
     77    def factory(*args): 
     78        return _Importer(config,*args) 
     79    return factory 
     80 
     81_installed=False 
     82def install_import_hook(factory): 
     83    global _installed 
     84    if not _installed: 
     85        path_hooks.append(factory) 
     86        _installed=True 
     87        path_importer_cache.clear() 
     88 
     89def remove_import_hook(): 
     90    i = 0 
     91    while i < len(path_hooks): 
     92        if isinstance(path_hooks[i], _Importer): 
     93            del path_hooks[i] 
     94        else: 
     95            i += 1 
     96    path_importer_cache.clear() 
     97}}} 
     98 
     99 
     100