Defining a custom template tag consists of three parts: a compiling function, a rendering `Node` subclass and a tag registration with `register.tag()`. The latter can be used as a (function) decorator on the compiling function, simplifying things into two parts. A neat fact is that `register.tag()` can actually be used as a class decorator in Python 2.6+ to condense all steps into the `Node` subclass. The compiling function simply becomes the `__init__()` of the class. Here's the 'current_time' tag example from the docs: {{{ import datetime from django import template register = template.Library() @register.tag('current_time') class CurrentTimeNode(template.Node): def __init__(self, parser, token): try: # split_contents() knows not to split quoted strings. tag_name, format_string = token.split_contents() except ValueError: raise template.TemplateSyntaxError, "%r tag requires a single argument" % token.contents.split()[0] if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")): raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name self.format_string = str(format_string[1:-1]) def render(self, context): return datetime.datetime.now().strftime(self.format_string) }}} or even simpler, leave off the name argument and use the class name as the tag name: {{{ import datetime from django import template register = template.Library() @register.tag class current_time(template.Node): def __init__(self, parser, token): try: # split_contents() knows not to split quoted strings. tag_name, format_string = token.split_contents() except ValueError: raise template.TemplateSyntaxError, "%r tag requires a single argument" % token.contents.split()[0] if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")): raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name self.format_string = str(format_string[1:-1]) def render(self, context): return datetime.datetime.now().strftime(self.format_string) }}}