# -*- coding: utf-8 -*- """ Template Decorator ~~~~~~~~~~~~~~~~~~ The decorator makes the callable return a 2-tuple of the template name and the return value (inspired by Buffet_). The template name is an optional argument. If not specified, the callable's name will be used. In both cases, the name of the callable's module will be prepended. This makes sense if a module represents the controller in a MVC (model/view/controller) application structure and contains multiple callables that represent its actions. E. g., CherryPy_ applications are usually structured this way. :Copyright: 2007-2008 Jochen Kupperschmidt :Date: 09-Jul-2008 :License: MIT .. _Buffet: http://projects.dowski.com/projects/buffet .. _CherryPy: http://cherrypy.org/ """ def use_template(arg): """Decorator to specify a template.""" if hasattr(arg, '__call__'): return set_template(arg) def wrapper(func): return set_template(func, arg) return wrapper def set_template(func, name=None): """Set a template for a controller action.""" ctrl = func.__module__.split('.')[-1] tpl = '%s_%s' % (ctrl, name or func.__name__) # Alternative: Set the template name as attribute of the callable and # don't touch the return value: # func.template = tpl # return func def inner(*args, **kwargs): return tpl, func(*args, **kwargs) return inner # Usage example follows. # It is assumed that the class is defined in a module 'blog.py'. However, it # is also possible to use plain functions instead of the class structure class Root(object): # Returns template name 'blog_index'. @use_template def index(self): """Show a list of items.""" # Returns template name 'blog_details'. @use_template('details') def view(self, id): """Show a single item."""