CherryPy Project Download

Here's a basic CherryPy Tool for using Jinja templates:

"""A Jinja Handler and tool.  This code is in the public domain.

Usage:
@cherrypy.expose
@cherrypy.tools.jinja(filename='index.html')
def controller(**kwargs):
    return {

    } # This dict is the template context     

"""

import jinja
from jinja.datastructure import ComplainingUndefined, SilentUndefinedType
from jinja.datastructure import make_undefined


class JinjaHandler(cherrypy.dispatch.LateParamPageHandler):
    """Callable which sets response.body."""

    def __init__(self, env, template_name, next_handler):
        self.env = env
        self.template_name = template_name
        self.next_handler = next_handler

    def __call__(self):
        context = {}
        try:
            r = self.next_handler()
            context.update(r)
        except ValueError, e:
            cherrypy.log('%s (handler for "%s" returned "%s")\n' % (
                e, self.template_name, repr(r)), traceback=True)

        # We wait until this point to do any tasks related to template 
        # loading or context building, as it may not be necessary if
        # the first handler causes a response and we never render
        # the template. (Minor Optimization)
        if cherrypy.config.get('template.show_errors', False):
            self.env.undefined_singleton = ComplainingUndefined
        context.update({
            'request': cherrypy.request,
            'app_url': cherrypy.request.app.script_name,
        })

        cherrypy.request.template = tmpl = self.env.get_template(self.template_name)
        output = tmpl.render(**context)

        return output

class LoggingUndefinedType(SilentUndefinedType):
    # object calling
    def __reduce__(self):
        return 'LoggingUndefined'

    def __unicode__(self):
        "At this point we're being rendered in a template, so we should log it."
        cherrypy.log("Coercing undefined object to unicode @%s" %
                     "".join(traceback.format_stack()),
                     severity=logging.ERROR)
        return u""

LoggingUndefined = make_undefined(LoggingUndefinedType)


class JinjaLoader(object):
    """A CherryPy 3 Tool for loading Jinja templates."""

    def __init__(self):

        self.template_dir_list = []
        self.env = jinja.Environment(loader=jinja.ChoiceLoader(self.template_dir_list),
                                     default_filters=[],
                                     undefined_singleton=LoggingUndefined,
                                     friendly_traceback=False)
        self.add_template_dir(os.path.join(thisdir, 'templates'))


    def __call__(self, filename):
        cherrypy.request.handler = JinjaHandler(self.env, filename, cherrypy.request.handler)
    def add_filter(self, func):
        """Decorator which adds the given function to jinja's filters."""
        self.env.filters[func.__name__] = func
        return func

    def add_global(self, func):
        """Decorator which adds the given function to jinja's globals."""
        self.env.globals[func.__name__] = func
        return func

return func


# FIXME: if templates grow more settings, we should consider using a namespace
cherrypy._cpconfig.environments['production']['template.show_errors'] = False
cherrypy._cpconfig.environments['staging']['template.show_errors'] = False
cherrypy._cpconfig.environments['development']['template.show_errors'] = True
cherrypy._cpconfig.environments['test_suite']['template.show_errors'] = False

loader = JinjaLoader()
cherrypy.tools.jinja = cherrypy.Tool('before_handler', loader, priority=70)

Hosted by WebFaction

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