template.py
changeset 46 54c5f5f340de
parent 42 5a72c00c4ae4
child 50 e4fbf480fbee
equal deleted inserted replaced
45:e94ab812c0c8 46:54c5f5f340de
       
     1 """
       
     2     Template handler
       
     3 """
       
     4 
       
     5 from mako import exceptions
       
     6 from mako.template import Template
       
     7 import mako.lookup
       
     8 
       
     9 from qmsk.web import http, helpers
       
    10 
       
    11 # path to template files
       
    12 TEMPLATE_DIR = "templates"
       
    13 
       
    14 # path to cached templates
       
    15 CACHE_DIR = "cache/templates"
       
    16 
       
    17 # template file extension
       
    18 TEMPLATE_EXT = "tmpl"
       
    19 
       
    20 class TemplateError (http.ResponseError) :
       
    21     """
       
    22         Raised by the template module functions
       
    23     """
       
    24 
       
    25     pass
       
    26 
       
    27 class TemplateLoader (mako.lookup.TemplateLookup) :
       
    28     """
       
    29         Our own specialization of mako's TemplateLookup
       
    30     """
       
    31 
       
    32     def __init__ (self, path, fileext=TEMPLATE_EXT, **env) :
       
    33         """
       
    34             Initialize to load templates located at path, with the given file extension.
       
    35 
       
    36             The given **env list is supplied to every template render
       
    37         """
       
    38 
       
    39         # store
       
    40         self.path = path
       
    41         self.fileext = fileext
       
    42         self.env = env
       
    43             
       
    44         # build the TemplateLookup
       
    45         super(TemplateLoader, self).__init__(directories=[path], module_directory=CACHE_DIR)
       
    46     
       
    47     @staticmethod
       
    48     def _render (tpl, env, params) :
       
    49         """
       
    50             Render the given template with given env/params, returning the output as a unicode string, or raising a TemplateError
       
    51         """
       
    52 
       
    53         # build the context from our superglobals, env, and params
       
    54         ctx = dict(
       
    55             h       = helpers,
       
    56         )
       
    57         ctx.update(env)
       
    58         ctx.update(params)
       
    59 
       
    60         try :
       
    61             return tpl.render_unicode(**ctx)
       
    62         
       
    63         # a template may render other templates
       
    64         except TemplateError :
       
    65             raise
       
    66 
       
    67         except :
       
    68             details = exceptions.text_error_template().render()
       
    69 
       
    70             raise TemplateError("Template render failed", status='500 Internal Server Error', details=details)
       
    71 
       
    72 
       
    73     def lookup (self, name) :
       
    74         """
       
    75             Looks up a template based on the bare "name", which does not include the path or file extension
       
    76         """
       
    77         
       
    78         try :
       
    79             return self.get_template("%s.%s" % (name, self.fileext))
       
    80 
       
    81         except :
       
    82             raise TemplateError("Template broken: %r" % (name, ), status='500 Internal Server Error', details=exceptions.text_error_template().render())
       
    83     
       
    84     def render (self, name, **params) :
       
    85         """
       
    86             Render a template, using lookup() on the given name
       
    87         """
       
    88 
       
    89         return self._render(self.lookup(name), self.env, params)
       
    90 
       
    91     def render_to_response (self, name, **params) :
       
    92         """
       
    93             Render a template, returning a http.Response object
       
    94         """
       
    95 
       
    96         return http.Response(self.render(name, **params))
       
    97 
       
    98     @classmethod
       
    99     def load (cls, path) :
       
   100         """
       
   101             Loads a template from a specific file
       
   102         """
       
   103 
       
   104         try :
       
   105             return Template(filename=path, module_directory=CACHE_DIR)
       
   106 
       
   107         except :
       
   108             raise TemplateError("Template broken: %r" % (path, ), status='500 Internal Server Error', details=exceptions.text_error_template().render())
       
   109     
       
   110     @classmethod
       
   111     def render_file (cls, path, **params) :
       
   112         """
       
   113             Render a template, using load() on the given path. No global environment vars are defined for the render.
       
   114         """
       
   115 
       
   116         return cls._render(cls.load(path), dict(), params)
       
   117 
       
   118     @classmethod
       
   119     def render_template (cls, template, **params) :
       
   120         """
       
   121             Render the given template object. No global environment vars are defined for the render.
       
   122         """
       
   123         
       
   124         return cls._render(template, dict(), params)