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