pythondjangodjango-templatestemplatetagsdjango-context

Django simple_tag and setting context variables


I'm trying to use a simple_tag and set a context variable. I'm using the trunk version of django:

from django import template

@register.simple_tag(takes_context=True)
def somefunction(context, obj):   
    return set_context_vars(obj)

class set_context_vars(template.Node):
    def __init__(self, obj):
        self.object = obj
    
    def render(self, context):
        context['var'] = 'somevar'
        return ''

This doesn't set the variable, but if I do something very similar with @register.tag it works but the object parameter doesn't pass through...

Thanks!


Solution

  • You are mixing two approaches here. A simple_tag is merely a helper function, which cuts down on some boilerplate code and is supposed to return a string. To set context variables, you need (at least with plain django) to write your own tag with a render method.

    from django import template
    
    register = template.Library()
    
    
    class FooNode(template.Node):
    
        def __init__(self, obj):
            # saves the passed obj parameter for later use
            # this is a template.Variable, because that way it can be resolved
            # against the current context in the render method
            self.object = template.Variable(obj)
    
        def render(self, context):
            # resolve allows the obj to be a variable name, otherwise everything
            # is a string
            obj = self.object.resolve(context)
            # obj now is the object you passed the tag
    
            context['var'] = 'somevar'
            return ''
    
    
    @register.tag
    def do_foo(parser, token):
        # token is the string extracted from the template, e.g. "do_foo my_object"
        # it will be splitted, and the second argument will be passed to a new
        # constructed FooNode
        try:
            tag_name, obj = token.split_contents()
        except ValueError:
            raise template.TemplateSyntaxError, "%r tag requires exactly one argument" % token.contents.split()[0]
        return FooNode(obj)
    

    This may be called like this:

    {% do_foo my_object %}
    {% do_foo 25 %}