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)