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__()
. Below are two variants of the 'current_time' tag example from the Django docs: the first passing an explicit tag name and the second using the class name instead.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | import datetime
from django import template
register = template.Library()
if 1: # explicit tag name
@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)
else: # implicit tag name
@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)
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 11 months ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 1 week ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
I see one disadvantage: can't inherit from a decorated class. This makes it impossible to reuse them. So, unless Library.tag is modified to handle classes as well, its use is limited. Except for that works perfect.
#
Please login first before commenting.