| 1 | 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. |
| 2 | |
| 3 | 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: |
| 4 | |
| 5 | {{{ |
| 6 | import datetime |
| 7 | from django import template |
| 8 | register = template.Library() |
| 9 | |
| 10 | @register.tag('current_time') |
| 11 | class CurrentTimeNode(template.Node): |
| 12 | def __init__(self, parser, token): |
| 13 | try: |
| 14 | # split_contents() knows not to split quoted strings. |
| 15 | tag_name, format_string = token.split_contents() |
| 16 | except ValueError: |
| 17 | raise template.TemplateSyntaxError, "%r tag requires a single argument" % token.contents.split()[0] |
| 18 | if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")): |
| 19 | raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name |
| 20 | self.format_string = str(format_string[1:-1]) |
| 21 | |
| 22 | def render(self, context): |
| 23 | return datetime.datetime.now().strftime(self.format_string) |
| 24 | }}} |
| 25 | |
| 26 | or even simpler, leave off the name argument and use the class name as the tag name: |
| 27 | |
| 28 | {{{ |
| 29 | import datetime |
| 30 | from django import template |
| 31 | register = template.Library() |
| 32 | |
| 33 | @register.tag |
| 34 | class current_time(template.Node): |
| 35 | def __init__(self, parser, token): |
| 36 | try: |
| 37 | # split_contents() knows not to split quoted strings. |
| 38 | tag_name, format_string = token.split_contents() |
| 39 | except ValueError: |
| 40 | raise template.TemplateSyntaxError, "%r tag requires a single argument" % token.contents.split()[0] |
| 41 | if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")): |
| 42 | raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name |
| 43 | self.format_string = str(format_string[1:-1]) |
| 44 | |
| 45 | def render(self, context): |
| 46 | return datetime.datetime.now().strftime(self.format_string) |
| 47 | }}} |