from django.template import Library from django.template import FilterExpression, Node, NodeList from django.template import TemplateSyntaxError, VariableDoesNotExist register = Library() def do_ifvalue(parser, token, name, negate=False): bits = list(token.split_contents()) if len(bits) != 2 and len(bits) != 4: raise TemplateSyntaxError, "%r takes one or three arguments" % bits[0] tagname, variable = tuple(bits)[:2] if len(bits) == 4: if bits[2] != "as": raise TemplateSyntaxError, "%r with three arguments must be 'value as name'" % tagname name = bits[3] end_tag = 'end' + tagname nodelist_true = parser.parse(('else', end_tag)) token = parser.next_token() if token.contents == 'else': nodelist_false = parser.parse((end_tag,)) parser.delete_first_token() else: nodelist_false = NodeList() expr = FilterExpression(variable, parser) return IfValueNode(expr, name, nodelist_true, nodelist_false, negate) @register.tag def ifvalue(parser, token, name="value"): """ Output the contents of the block if the argument is true, assigning the value of the argument to a context variable ("value" by default). Examples:: {% ifvalue user.name %} {{ value }} ... {% else %} ... {% endifvalue %} {% ifvalue user.name as username %} {{ username }} ... {% else %} ... {% endifvalue %} """ return do_ifvalue(parser, token, name, False) @register.tag def ifnotvalue(parser, token, name="value"): """Output the contents of the block if the argument is false. See ifvalue.""" return do_ifvalue(parser, token, name, True) class IfValueNode(Node): def __init__(self, var, name, nodelist_true, nodelist_false, negate): self.var = var self.name = name self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false self.negate = negate def __repr__(self): return "" def render(self, context): val = self.var.resolve(context, ignore_failures=True) context[self.name] = val if (self.negate and not val) or (not self.negate and val): return self.nodelist_true.render(context) return self.nodelist_false.render(context) def get_nodes_by_type(self, nodetype): nodes = [] if isinstance(self, nodetype): nodes.append(self) nodes.extend(self.nodelist_true.get_nodes_by_type(nodetype)) nodes.extend(self.nodelist_false.get_nodes_by_type(nodetype)) return nodes