[Fixed]-Define custom django template tag on the fly

1👍

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.

0👍

Just in case anyone needs it, it’s actually quite simple if you look at the source for Django’s own {% load %} tag:

Approach

  1. define a static tag, e.g. {% import_dynamic_tags %}
  2. the parser function for this tag gives you access to the parser instance, which offers an add_library() method
  3. the argument for add_library is simply a new instance of django.template.base.Library
  4. at the new instance of Library, just call tag() or filter() to create dynamic templatetags and filters

Example

This 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()
👤chrisv

Leave a comment