| 1106 | |
| 1107 | |
| 1108 | class SwitchNode(Node): |
| 1109 | def __init__(self, var1, nodelist_true, nodelist_false): |
| 1110 | self.comparison_base = Variable(var1) |
| 1111 | self.nodelist_true = nodelist_true |
| 1112 | self.nodelist_false = nodelist_false |
| 1113 | |
| 1114 | def __repr__(self): |
| 1115 | return "<SwitchNode>" |
| 1116 | |
| 1117 | def render(self, context): |
| 1118 | try: |
| 1119 | val1 = self.comparison_base.resolve(context) |
| 1120 | context['%BASE_COMPARISON%'] = val1 |
| 1121 | except VariableDoesNotExist: |
| 1122 | raise TemplateSyntaxError("Could not resolve variable %r in current context" % \ |
| 1123 | self.comparison_base.var) |
| 1124 | ok = False |
| 1125 | for node in self.nodelist_true: |
| 1126 | if isinstance(node, CaseNode): |
| 1127 | if node.get_bool(context): |
| 1128 | ok = True |
| 1129 | if ok: |
| 1130 | return self.nodelist_true.render(context) |
| 1131 | else: |
| 1132 | return self.nodelist_false.render(context) |
| 1133 | |
| 1134 | |
| 1135 | def do_switch(parser, token): |
| 1136 | """ |
| 1137 | Create a context to use case-like coditional |
| 1138 | template rendering. |
| 1139 | |
| 1140 | For example:: |
| 1141 | |
| 1142 | {% switch person.name %} |
| 1143 | {% case 'John Doe' %} |
| 1144 | Hi! My name is John, the master! |
| 1145 | {% endcase %} |
| 1146 | {% case 'Mary Jane' %} |
| 1147 | Hello! My name is Mary. Nice to meet you! |
| 1148 | {% endcase %} |
| 1149 | {% default %} |
| 1150 | Oh my God! I have no name! |
| 1151 | {% endswitch %} |
| 1152 | """ |
| 1153 | |
| 1154 | bits = list(token.split_contents()) |
| 1155 | if len(bits) != 2: |
| 1156 | raise TemplateSyntaxError, "%r takes one argument" % bits[0] |
| 1157 | end_tag = 'end' + bits[0] |
| 1158 | nodelist_true = parser.parse(('default', end_tag,)) |
| 1159 | token = parser.next_token() |
| 1160 | if token.contents == 'default': |
| 1161 | nodelist_false = parser.parse((end_tag,)) |
| 1162 | parser.delete_first_token() |
| 1163 | else: |
| 1164 | nodelist_false = NodeList() |
| 1165 | return SwitchNode(bits[1], nodelist_true, nodelist_false) |
| 1166 | do_switch = register.tag('switch', do_switch) |
| 1167 | |
| 1168 | class CaseNode(Node): |
| 1169 | def __init__(self, var, nodelist): |
| 1170 | self.var = Variable(var) |
| 1171 | self.nodelist = nodelist |
| 1172 | |
| 1173 | def __repr__(self): |
| 1174 | return "<CaseNode>" |
| 1175 | |
| 1176 | def get_bool(self, context): |
| 1177 | try: |
| 1178 | val = self.var.resolve(context) |
| 1179 | except VariableDoesNotExist: |
| 1180 | val = None |
| 1181 | if context.get("%BASE_COMPARISON%", None) == val: |
| 1182 | return True |
| 1183 | else: |
| 1184 | return False |
| 1185 | |
| 1186 | def render(self, context): |
| 1187 | if self.get_bool(context): |
| 1188 | return self.nodelist.render(context) |
| 1189 | else: |
| 1190 | return NodeList().render(context) |
| 1191 | |
| 1192 | @register.tag |
| 1193 | def do_case(parser, token): |
| 1194 | bits = list(token.split_contents()) |
| 1195 | if len(bits) != 2: |
| 1196 | raise TemplateSyntaxError, "%r takes one argument" % bits[0] |
| 1197 | end_tag = 'end' + bits[0] |
| 1198 | nodelist_true = parser.parse(('else', end_tag)) |
| 1199 | token = parser.next_token() |
| 1200 | if token.contents == 'else': |
| 1201 | nodelist_false = parser.parse((end_tag,)) |
| 1202 | parser.delete_first_token() |
| 1203 | else: |
| 1204 | nodelist_false = NodeList() |
| 1205 | return CaseNode(bits[1], nodelist_true) |
| 1206 | do_case = register.tag('case', do_case) |