Ticket #7711: improving_the_context_filling.patch

File improving_the_context_filling.patch, 5.0 KB (added by Gabriel Falcão, 16 years ago)

Adding support to nested switches

  • django/template/defaulttags.py

     
    22
    33import sys
    44import re
     5import md5
    56from itertools import cycle as itertools_cycle
    67try:
    78    reversed
     
    11031104    parser.delete_first_token()
    11041105    return WithNode(var, name, nodelist)
    11051106do_with = register.tag('with', do_with)
     1107
     1108
     1109class 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
     1138def 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)
     1169do_switch = register.tag('switch', do_switch)
     1170
     1171class 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   
     1207def 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
     1216do_case = register.tag('case', do_case)
  • docs/templates.txt

     
    12181218The populated variable (in the example above, ``total``) is only available
    12191219between the ``{% with %}`` and ``{% endwith %}`` tags.
    12201220
     1221switch
     1222~~~~
     1223
     1224**New in Django development version**
     1225
     1226Stores a variable for internal comparison with a ``{% case %}`` tag.
     1227This is useful comparing an "expensive" sequence of instructions ``{% ifequal %}``.
     1228
     1229For example::
     1230
     1231    {% switch person.name %}
     1232        {% case 'John Doe' %}
     1233            Hi! My name is John, the master!
     1234        {% endcase %}
     1235        {% case 'Mary Jane' %}
     1236            Hello! My name is Mary. Nice to meet you!
     1237        {% endcase %}           
     1238    {% default %}
     1239        Oh my God! I have no name!
     1240    {% endswitch %}
     1241
     1242The tag ``case`` above SHALL be used only within  ``{% switch %}`` and ``{% endswitch %}`` tags.
     1243
     1244
    12211245Built-in filter reference
    12221246-------------------------
    12231247
Back to Top