动态定义自定义django模板标记

时间:2015-09-20 08:48:05

标签: django django-templates

django中是否有办法“动态”声明自定义模板标签?

例如,如果我有一个呈现树结构的页面并且我的标签可以工作,那么它需要root和leaf。既然我现在将使用此标签与此根(在页面上),一旦我知道将使用哪个根,有没有办法创建模板?

在我的模板中,我目前使用:

{% render_leaf root leaf %}

我想创建“动态”标签(在获取根目录之后),以便root现在是标记函数的局部变量,我可以简单地调用:{% render_leaf leaf %}

2 个答案:

答案 0 :(得分:1)

将解决方案的动态部分移动到您的视图(如评论中所述),并在模板的上下文中传递正确的根和叶子会容易得多。这样做应该使模板真正直接。

答案 1 :(得分:0)

万一有人需要它,如果你查看Django自己的{% load %}标签的来源,实际上很简单:

方法

  1. 定义静态标记,例如{% import_dynamic_tags %}
  2. 此标记的解析器功能可让您访问parser实例,该实例提供add_library()方法
  3. add_library的参数只是django.template.base.Library
  4. 的新实例
  5. Library的新实例中,只需致电tag()filter()即可创建动态模板标签和过滤器
  6. 实施例

    此代码必须放在常规模板库中,例如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()