# $Id$ # simple django-style templating. # # see: http://effbot.org/zone/django-simple-template.htm import re import cgi, string TEMPLATE_STRING_IF_INVALID = "" FILTERS = { "escape": cgi.escape, "upper": string.upper, "lower": string.lower, } ## # Renders a Django-style template, using variables from the given # context object. # # @param template A Django-style template. Only variables are currently # supported. # @param context A context object. This can be any object that provides # the attributes, methods, or members that are used by the template. # @return A list of string fragments. def render(template, context): next = iter(re.split("({{|}})", template)).next data = [] try: token = next() while 1: if token == "{{": # variable data.append(variable(next(), context)) if next() != "}}": raise SyntaxError("missing variable terminator") else: data.append(token) # literal token = next() except StopIteration: pass return data def variable(name, context): name = name.strip() if "|" in name: name, filters = name.split("|", 1) else: filters = None obj = context for item in name.split("."): try: obj = obj[item] # dictionary member except (KeyError, AttributeError, TypeError): try: obj = getattr(obj, item) # or attribute except AttributeError: obj = TEMPLATE_STRING_IF_INVALID break else: if callable(obj): # or method obj = obj() if filters: try: obj = FILTERS[filters](obj) except KeyError: pass return obj