Ticket #17348: 17348.patch

File 17348.patch, 7.4 KB (added by Aymeric Augustin, 12 years ago)
  • docs/ref/templates/builtins.txt

     
    356356
    357357    {% if athlete_list %}
    358358        Number of athletes: {{ athlete_list|length }}
     359    {% elif athlete_in_locker_room_list %}
     360        Athletes should be out of the locker room soon!
    359361    {% else %}
    360362        No athletes.
    361363    {% endif %}
     
    363365In the above, if ``athlete_list`` is not empty, the number of athletes will be
    364366displayed by the ``{{ athlete_list|length }}`` variable.
    365367
    366 As you can see, the ``if`` tag can take an optional ``{% else %}`` clause that
    367 will be displayed if the test fails.
     368As you can see, the ``if`` tag may take one or several `` {% elif %}``
     369clauses, as well as an ``{% else %}`` clause that will be displayed if all
     370previous conditions fail. These clauses are optional.
    368371
     372.. versionadded:: 1.4
     373
     374The ``if`` tag now supports ``{% elif %}`` clauses.
     375
    369376Boolean operators
    370377^^^^^^^^^^^^^^^^^
    371378
  • tests/regressiontests/templates/tests.py

     
    394394        try:
    395395            t = Template("{% if 1 %}lala{% endblock %}{% endif %}")
    396396        except TemplateSyntaxError, e:
    397             self.assertEqual(e.args[0], "Invalid block tag: 'endblock', expected 'else' or 'endif'")
     397            self.assertEqual(e.args[0], "Invalid block tag: 'endblock', expected 'elif', 'else' or 'endif'")
    398398
    399399    def test_templates(self):
    400400        template_tests = self.get_template_tests()
     
    822822            'if-tag02': ("{% if foo %}yes{% else %}no{% endif %}", {"foo": False}, "no"),
    823823            'if-tag03': ("{% if foo %}yes{% else %}no{% endif %}", {}, "no"),
    824824
     825            'if-tag04': ("{% if foo %}foo{% elif bar %}bar{% endif %}", {'foo': True}, "foo"),
     826            'if-tag05': ("{% if foo %}foo{% elif bar %}bar{% endif %}", {'bar': True}, "bar"),
     827            'if-tag06': ("{% if foo %}foo{% elif bar %}bar{% endif %}", {}, ""),
     828            'if-tag07': ("{% if foo %}foo{% elif bar %}bar{% else %}nothing{% endif %}", {'foo': True}, "foo"),
     829            'if-tag08': ("{% if foo %}foo{% elif bar %}bar{% else %}nothing{% endif %}", {'bar': True}, "bar"),
     830            'if-tag09': ("{% if foo %}foo{% elif bar %}bar{% else %}nothing{% endif %}", {}, "nothing"),
     831            'if-tag10': ("{% if foo %}foo{% elif bar %}bar{% elif baz %}baz{% else %}nothing{% endif %}", {'foo': True}, "foo"),
     832            'if-tag11': ("{% if foo %}foo{% elif bar %}bar{% elif baz %}baz{% else %}nothing{% endif %}", {'bar': True}, "bar"),
     833            'if-tag12': ("{% if foo %}foo{% elif bar %}bar{% elif baz %}baz{% else %}nothing{% endif %}", {'baz': True}, "baz"),
     834            'if-tag13': ("{% if foo %}foo{% elif bar %}bar{% elif baz %}baz{% else %}nothing{% endif %}", {}, "nothing"),
     835
    825836            # Filters
    826837            'if-tag-filter01': ("{% if foo|length == 5 %}yes{% else %}no{% endif %}", {'foo': 'abcde'}, "yes"),
    827838            'if-tag-filter02': ("{% if foo|upper == 'ABC' %}yes{% else %}no{% endif %}", {}, "no"),
  • django/template/defaulttags.py

     
    250250        return self.nodelist_false.render(context)
    251251
    252252class IfNode(Node):
    253     child_nodelists = ('nodelist_true', 'nodelist_false')
    254253
    255     def __init__(self, var, nodelist_true, nodelist_false=None):
    256         self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
    257         self.var = var
     254    def __init__(self, conditions_nodelists):
     255        self.conditions_nodelists = conditions_nodelists
    258256
    259257    def __repr__(self):
    260         return "<If node>"
     258        return "<IfNode>"
    261259
    262260    def __iter__(self):
    263         for node in self.nodelist_true:
    264             yield node
    265         for node in self.nodelist_false:
    266             yield node
     261        for _, nodelist in self.conditions_nodelists:
     262            for node in nodelist:
     263                yield node
    267264
     265    @property
     266    def nodelist(self):
     267        return NodeList(node for _, nodelist in self.conditions_nodelists for node in nodelist)
     268
    268269    def render(self, context):
    269         try:
    270             var = self.var.eval(context)
    271         except VariableDoesNotExist:
    272             var = None
     270        for condition, nodelist in self.conditions_nodelists:
    273271
    274         if var:
    275             return self.nodelist_true.render(context)
    276         else:
    277             return self.nodelist_false.render(context)
     272            if condition is not None:           # if / elif clause
     273                try:
     274                    match = condition.eval(context)
     275                except VariableDoesNotExist:
     276                    match = None
     277            else:                               # else clause
     278                match = True
    278279
     280            if match:
     281                return nodelist.render(context)
     282
     283        return ''
     284
    279285class RegroupNode(Node):
    280286    def __init__(self, target, expression, var_name):
    281287        self.target, self.expression = target, expression
     
    825831
    826832        {% if athlete_list %}
    827833            Number of athletes: {{ athlete_list|count }}
     834        {% elif athlete_in_locker_room_list %}
     835            Athletes should be out of the locker room soon!
    828836        {% else %}
    829837            No athletes.
    830838        {% endif %}
     
    832840    In the above, if ``athlete_list`` is not empty, the number of athletes will
    833841    be displayed by the ``{{ athlete_list|count }}`` variable.
    834842
    835     As you can see, the ``if`` tag can take an option ``{% else %}`` clause
    836     that will be displayed if the test fails.
     843    As you can see, the ``if`` tag may take one or several `` {% elif %}``
     844    clauses, as well as an ``{% else %}`` clause that will be displayed if all
     845    previous conditions fail. These clauses are optional.
    837846
    838847    ``if`` tags may use ``or``, ``and`` or ``not`` to test a number of
    839848    variables or to negate a given variable::
     
    871880
    872881    Operator precedence follows Python.
    873882    """
     883    # {% if ... %}
    874884    bits = token.split_contents()[1:]
    875     var = TemplateIfParser(parser, bits).parse()
    876     nodelist_true = parser.parse(('else', 'endif'))
     885    condition = TemplateIfParser(parser, bits).parse()
     886    nodelist = parser.parse(('elif', 'else', 'endif'))
     887    conditions_nodelists = [(condition, nodelist)]
    877888    token = parser.next_token()
     889
     890    # {% elif ... %} (repeatable)
     891    while token.contents.startswith('elif'):
     892        bits = token.split_contents()[1:]
     893        condition = TemplateIfParser(parser, bits).parse()
     894        nodelist = parser.parse(('elif', 'else', 'endif'))
     895        conditions_nodelists.append((condition, nodelist))
     896        token = parser.next_token()
     897
     898    # {% else %} (optional)
    878899    if token.contents == 'else':
    879         nodelist_false = parser.parse(('endif',))
    880         parser.delete_first_token()
    881     else:
    882         nodelist_false = NodeList()
    883     return IfNode(var, nodelist_true, nodelist_false)
     900        nodelist = parser.parse(('endif'))
     901        conditions_nodelists.append((None, nodelist))
     902        token = parser.next_token()
    884903
     904    # {% endif %}
     905    assert token.contents == 'endif'
     906
     907    return IfNode(conditions_nodelists)
     908
     909
    885910@register.tag
    886911def ifchanged(parser, token):
    887912    """
Back to Top