template.py
changeset 46 54c5f5f340de
parent 42 5a72c00c4ae4
child 50 e4fbf480fbee
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/template.py	Sun Feb 08 03:17:07 2009 +0200
@@ -0,0 +1,124 @@
+"""
+    Template handler
+"""
+
+from mako import exceptions
+from mako.template import Template
+import mako.lookup
+
+from qmsk.web import http, helpers
+
+# path to template files
+TEMPLATE_DIR = "templates"
+
+# path to cached templates
+CACHE_DIR = "cache/templates"
+
+# template file extension
+TEMPLATE_EXT = "tmpl"
+
+class TemplateError (http.ResponseError) :
+    """
+        Raised by the template module functions
+    """
+
+    pass
+
+class TemplateLoader (mako.lookup.TemplateLookup) :
+    """
+        Our own specialization of mako's TemplateLookup
+    """
+
+    def __init__ (self, path, fileext=TEMPLATE_EXT, **env) :
+        """
+            Initialize to load templates located at path, with the given file extension.
+
+            The given **env list is supplied to every template render
+        """
+
+        # store
+        self.path = path
+        self.fileext = fileext
+        self.env = env
+            
+        # build the TemplateLookup
+        super(TemplateLoader, self).__init__(directories=[path], module_directory=CACHE_DIR)
+    
+    @staticmethod
+    def _render (tpl, env, params) :
+        """
+            Render the given template with given env/params, returning the output as a unicode string, or raising a TemplateError
+        """
+
+        # build the context from our superglobals, env, and params
+        ctx = dict(
+            h       = helpers,
+        )
+        ctx.update(env)
+        ctx.update(params)
+
+        try :
+            return tpl.render_unicode(**ctx)
+        
+        # a template may render other templates
+        except TemplateError :
+            raise
+
+        except :
+            details = exceptions.text_error_template().render()
+
+            raise TemplateError("Template render failed", status='500 Internal Server Error', details=details)
+
+
+    def lookup (self, name) :
+        """
+            Looks up a template based on the bare "name", which does not include the path or file extension
+        """
+        
+        try :
+            return self.get_template("%s.%s" % (name, self.fileext))
+
+        except :
+            raise TemplateError("Template broken: %r" % (name, ), status='500 Internal Server Error', details=exceptions.text_error_template().render())
+    
+    def render (self, name, **params) :
+        """
+            Render a template, using lookup() on the given name
+        """
+
+        return self._render(self.lookup(name), self.env, params)
+
+    def render_to_response (self, name, **params) :
+        """
+            Render a template, returning a http.Response object
+        """
+
+        return http.Response(self.render(name, **params))
+
+    @classmethod
+    def load (cls, path) :
+        """
+            Loads a template from a specific file
+        """
+
+        try :
+            return Template(filename=path, module_directory=CACHE_DIR)
+
+        except :
+            raise TemplateError("Template broken: %r" % (path, ), status='500 Internal Server Error', details=exceptions.text_error_template().render())
+    
+    @classmethod
+    def render_file (cls, path, **params) :
+        """
+            Render a template, using load() on the given path. No global environment vars are defined for the render.
+        """
+
+        return cls._render(cls.load(path), dict(), params)
+
+    @classmethod
+    def render_template (cls, template, **params) :
+        """
+            Render the given template object. No global environment vars are defined for the render.
+        """
+        
+        return cls._render(template, dict(), params)