Reputation: 1671
Is there a way in django to declare a custom template tag "on the fly"?
For example, if I have a page that renders an a tree structure and for my tag to work, it needs the root and the leaf. Since I now that I will use this tag only with this root (on the page), is there a way to create the template once I know which root will be used?
In my templates, I currently use:
{% render_leaf root leaf %}
I would like to create the tag "on the fly" (just after fetching the root), so that the root is now a local variable of the tag function, and I can simply call: {% render_leaf leaf %}
Upvotes: 0
Views: 242
Reputation: 1481
Just in case anyone needs it, it's actually quite simple if you look at the source for Django's own {% load %}
tag:
{% import_dynamic_tags %}
parser
instance, which offers an add_library()
methodadd_library
is simply a new instance of django.template.base.Library
Library
, just call tag()
or filter()
to create dynamic templatetags and filtersThis code must be placed inside a regular template library, e.g. myapp.templatetags.dynamic_tags
:
from django.template.base import Node, Library
register = template.Library()
class DummyNode(Node):
"""
empty DummyNode, required since a parser function
must return a Node instance
"""
def render(self, context):
return ''
@register.tag
def import_dynamic_tags(parser, token):
# create a new template library
lib = Library()
# create an "uppercase" filter dynamically. Library.filter()
# expects a name, a filter function and optional flags like takes_context
lib.filter('uppercase', lambda x: x.upper(), )
# create a custom "{% foo %}" templatetag. Library.tag()
# expects a name and a compiler function (the function you would normally
# decorate with @register_tag)
lib.tag('foo', foo_func)
# finally, tell the parser about our newly created library
parser.add_library(lib)
# filter functions MUST return a node, so just return DummyNode which
# does nothing at render time
return DummyNode()
Upvotes: 0
Reputation: 916
It would be far easier to move the dynamic part of the solution into your view (as mentioned in comments), and pass the correct root and leaves in the template's context. Doing this should then make the template really straight forward.
Upvotes: 1