1 # -*- coding: utf-8 -*-
2 # Source: http://djangosnippets.org/snippets/967/
4 # Posted: August 13, 2008
7 # We can use it based on djangosnippets Terms of Service:
8 # (http://djangosnippets.org/about/tos/)
10 # 2. That you grant any third party who sees the code you post
11 # a royalty-free, non-exclusive license to copy and distribute that code
12 # and to make and distribute derivative works based on that code. You may
13 # include license terms in snippets you post, if you wish to use
14 # a particular license (such as the BSD license or GNU GPL), but that
15 # license must permit royalty-free copying, distribution and modification
16 # of the code to which it is applied.
18 from django import template
19 from django.template import Library, Node, VariableDoesNotExist
24 @register.tag(name="switch")
25 def do_switch(parser, token):
27 The ``{% switch %}`` tag compares a variable against one or more values in
28 ``{% case %}`` tags, and outputs the contents of the matching block. An
29 optional ``{% else %}`` tag sets off the default output if no matches
32 {% switch result_count %}
34 There are no search results.
36 There is one search result.
38 Jackpot! Your search found {{ result_count }} results.
41 Each ``{% case %}`` tag can take multiple values to compare the variable
45 {% case "Jim" "Bob" "Joe" %}
46 Me old mate {{ username }}! How ya doin?
51 bits = token.contents.split()
54 raise template.TemplateSyntaxError("'%s' tag requires one argument" % tag_name)
55 variable = parser.compile_filter(bits[1])
57 class BlockTagList(object):
58 # This is a bit of a hack, as it embeds knowledge of the behaviour
59 # of Parser.parse() relating to the "parse_until" argument.
60 def __init__(self, *names):
61 self.names = set(names)
63 def __contains__(self, token_contents):
64 name = token_contents.split()[0]
65 return name in self.names
67 # Skip over everything before the first {% case %} tag
68 parser.parse(BlockTagList('case', 'endswitch'))
71 token = parser.next_token()
74 while token.contents != 'endswitch':
75 nodelist = parser.parse(BlockTagList('case', 'else', 'endswitch'))
78 raise template.TemplateSyntaxError("'else' must be last tag in '%s'." % tag_name)
80 contents = token.contents.split()
81 token_name, token_args = contents[0], contents[1:]
83 if token_name == 'case':
84 tests = map(parser.compile_filter, token_args)
85 case = (tests, nodelist)
89 case = (None, nodelist)
92 token = parser.next_token()
95 raise template.TemplateSyntaxError("'%s' must have at least one 'case'." % tag_name)
97 return SwitchNode(variable, cases)
100 class SwitchNode(Node):
101 def __init__(self, variable, cases):
102 self.variable = variable
106 return "<Switch node>"
109 for tests, nodelist in self.cases:
110 for node in nodelist:
113 def get_nodes_by_type(self, nodetype):
115 if isinstance(self, nodetype):
117 for tests, nodelist in self.cases:
118 nodes.extend(nodelist.get_nodes_by_type(nodetype))
121 def render(self, context):
123 value_missing = False
124 value = self.variable.resolve(context, True)
125 except VariableDoesNotExist:
130 for tests, nodelist in self.cases:
132 return nodelist.render(context)
133 elif not value_missing:
135 test_value = test.resolve(context, True)
136 if value == test_value:
137 return nodelist.render(context)