lib/template.py
author Tero Marttila <terom@fixme.fi>
Sat, 07 Feb 2009 21:21:10 +0200
branchsites
changeset 40 71ab68f31a1c
parent 32 be954df4f0e8
child 42 5a72c00c4ae4
permissions -rw-r--r--
the handlers work now
"""
    Template handler
"""

# use Mako
from mako import exceptions
from mako.template import Template
import mako.lookup

# for http.ResponseError
import http

import 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

def render (tpl, **params) :
    """
        Render the given template, returning the output as a unicode string, or raising a TemplateError
    """

    try :
        return tpl.render_unicode(
            # global helper stuff
            h           = helpers,

            # render-specific params
            **params
        )
    
    # 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)

class TemplateLoader (mako.lookup.TemplateLookup) :
    """
        Our own specialization of mako's TemplateLookup
    """

    def __init__ (self, path, fileext=TEMPLATE_EXT) :
        """
            Initialize to load templates located at path, with the given file extension
        """

        # store
        self.path = path
        self.fileext = fileext
        
        # XXX: separate cache?
        super(TemplateLoader, self).__init__(directories=[path], module_directory=CACHE_DIR)

    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 render(self.lookup(name), **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
        """

        return render(cls.load(path), **params)