Switch template tag

The {% switch %} tag compares a variable against one or more values in
{% case %} tags, and outputs the contents of the matching block. An
optional {% else %} tag sets off the default output if no matches
could be found:

fromdjangoimporttemplatefromdjango.templateimportLibrary,Node,VariableDoesNotExistregister=Library()@register.tag(name="switch")defdo_switch(parser,token):""" The ``{% switch %}`` tag compares a variable against one or more values in ``{% case %}`` tags, and outputs the contents of the matching block. An optional ``{% else %}`` tag sets off the default output if no matches could be found:: {% switch result_count %} {% case 0 %} There are no search results. {% case 1 %} There is one search result. {% else %} Jackpot! Your search found {{ result_count }} results. {% endswitch %} Each ``{% case %}`` tag can take multiple values to compare the variable against:: {% switch username %} {% case "Jim" "Bob" "Joe" %} Me old mate {{ username }}! How ya doin? {% else %} Hello {{ username }} {% endswitch %} """bits=token.contents.split()tag_name=bits[0]iflen(bits)!=2:raisetemplate.TemplateSyntaxError("'%s' tag requires one argument"%tag_name)variable=parser.compile_filter(bits[1])classBlockTagList(object):# This is a bit of a hack, as it embeds knowledge of the behaviour# of Parser.parse() relating to the "parse_until" argument.def__init__(self,*names):self.names=set(names)def__contains__(self,token_contents):name=token_contents.split()[0]returnnameinself.names# Skip over everything before the first {% case %} tagparser.parse(BlockTagList('case','endswitch'))cases=[]token=parser.next_token()got_case=Falsegot_else=Falsewhiletoken.contents!='endswitch':nodelist=parser.parse(BlockTagList('case','else','endswitch'))ifgot_else:raisetemplate.TemplateSyntaxError("'else' must be last tag in '%s'."%tag_name)contents=token.contents.split()token_name,token_args=contents[0],contents[1:]iftoken_name=='case':tests=map(parser.compile_filter,token_args)case=(tests,nodelist)got_case=Trueelse:# The {% else %} tagcase=(None,nodelist)got_else=Truecases.append(case)token=parser.next_token()ifnotgot_case:raisetemplate.TemplateSyntaxError("'%s' must have at least one 'case'."%tag_name)returnSwitchNode(variable,cases)classSwitchNode(Node):def__init__(self,variable,cases):self.variable=variableself.cases=casesdef__repr__(self):return"<Switch node>"def__iter__(self):fortests,nodelistinself.cases:fornodeinnodelist:yieldnodedefget_nodes_by_type(self,nodetype):nodes=[]ifisinstance(self,nodetype):nodes.append(self)fortests,nodelistinself.cases:nodes.extend(nodelist.get_nodes_by_type(nodetype))returnnodesdefrender(self,context):try:value_missing=Falsevalue=self.variable.resolve(context,True)exceptVariableDoesNotExist:no_value=Truevalue_missing=Nonefortests,nodelistinself.cases:iftestsisNone:returnnodelist.render(context)elifnotvalue_missing:fortestintests:test_value=test.resolve(context,True)ifvalue==test_value:returnnodelist.render(context)else:return""