Django

Code

Changeset 9530

Show
Ignore:
Timestamp:
11/24/08 16:01:48 (7 months ago)
Author:
jacob
Message:

Fixed #6398: added an optional {% empty %} clause to the {% for %} template tag. The contents of this clause are rendered if the list iterated over turns out to be empty. Thanks, Jannis Leidel.

Astute readers will notice that the patch originally called this default; after consideration I decided that empty is a very slightly better color for this particular bikeshed.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/template/defaulttags.py

    r8716 r9530  
    8484 
    8585class ForNode(Node): 
    86     def __init__(self, loopvars, sequence, is_reversed, nodelist_loop): 
     86    def __init__(self, loopvars, sequence, is_reversed, nodelist_loop, nodelist_empty=None): 
    8787        self.loopvars, self.sequence = loopvars, sequence 
    8888        self.is_reversed = is_reversed 
    8989        self.nodelist_loop = nodelist_loop 
     90        if nodelist_empty is None: 
     91            self.nodelist_empty = NodeList() 
     92        else: 
     93            self.nodelist_empty = nodelist_empty 
    9094 
    9195    def __repr__(self): 
     
    98102        for node in self.nodelist_loop: 
    99103            yield node 
     104        for node in self.nodelist_empty: 
     105            yield node 
    100106 
    101107    def get_nodes_by_type(self, nodetype): 
     
    104110            nodes.append(self) 
    105111        nodes.extend(self.nodelist_loop.get_nodes_by_type(nodetype)) 
     112        nodes.extend(self.nodelist_empty.get_nodes_by_type(nodetype)) 
    106113        return nodes 
    107114 
    108115    def render(self, context): 
    109         nodelist = NodeList() 
    110116        if 'forloop' in context: 
    111117            parentloop = context['forloop'] 
     
    122128            values = list(values) 
    123129        len_values = len(values) 
     130        if len_values < 1: 
     131            return self.nodelist_empty.render(context) 
     132        nodelist = NodeList() 
    124133        if self.is_reversed: 
    125134            values = reversed(values) 
     
    611620        {% endfor %} 
    612621 
     622    The ``for`` tag can take an optional ``{% empty %}`` clause that will 
     623    be displayed if the given array is empty or could not be found:: 
     624 
     625        <ul> 
     626          {% for athlete in athlete_list %} 
     627            <li>{{ athlete.name }}</li> 
     628          {% empty %} 
     629            <li>Sorry, no athletes in this list.</li> 
     630          {% endfor %} 
     631        <ul> 
     632         
     633    The above is equivalent to -- but shorter, cleaner, and possibly faster 
     634    than -- the following:: 
     635     
     636        <ul> 
     637          {% if althete_list %} 
     638            {% for athlete in athlete_list %} 
     639              <li>{{ athlete.name }}</li> 
     640            {% endfor %} 
     641          {% else %} 
     642            <li>Sorry, no athletes in this list.</li> 
     643          {% endif %} 
     644        </ul> 
     645 
    613646    The for loop sets a number of variables available within the loop: 
    614647 
     
    647680 
    648681    sequence = parser.compile_filter(bits[in_index+1]) 
    649     nodelist_loop = parser.parse(('endfor',)) 
    650     parser.delete_first_token() 
    651     return ForNode(loopvars, sequence, is_reversed, nodelist_loop) 
     682    nodelist_loop = parser.parse(('default', 'endfor',)) 
     683    token = parser.next_token() 
     684    if token.contents == 'default': 
     685        nodelist_default = parser.parse(('endfor',)) 
     686        parser.delete_first_token() 
     687    else: 
     688        nodelist_default = None 
     689    return ForNode(loopvars, sequence, is_reversed, nodelist_loop, nodelist_default) 
    652690do_for = register.tag("for", do_for) 
    653691 
  • django/trunk/docs/ref/templates/builtins.txt

    r9529 r9530  
    234234                                current one 
    235235    ==========================  ================================================ 
     236 
     237for ... empty 
     238^^^^^^^^^^^^^ 
     239 
     240.. versionadded:: 1.1 
     241 
     242The ``for`` tag can take an optional ``{% empty %}`` clause that will be 
     243displayed if the given array is empty or could not be found:: 
     244 
     245    <ul> 
     246    {% for athlete in athlete_list %} 
     247        <li>{{ athlete.name }}</li> 
     248    {% empty %} 
     249        <li>Sorry, no athlete in this list!</li> 
     250    {% endfor %} 
     251    <ul> 
     252 
     253The above is equivalent to -- but shorter, cleaner, and possibly faster 
     254than -- the following:: 
     255 
     256    <ul> 
     257      {% if althete_list %} 
     258        {% for athlete in athlete_list %} 
     259          <li>{{ athlete.name }}</li> 
     260        {% endfor %} 
     261      {% else %} 
     262        <li>Sorry, no athletes in this list.</li> 
     263      {% endif %} 
     264    </ul> 
    236265 
    237266.. templatetag:: if 
  • django/trunk/tests/regressiontests/templates/tests.py

    r9161 r9530  
    485485            'for-tag-unpack12': ("{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}", {"items": (('one', 1, 'carrot'), ('two', 2))}, ("one:1,carrot/two:2,/", "one:1,carrot/two:2,INVALID/")), 
    486486            'for-tag-unpack13': ("{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}", {"items": (('one', 1, 'carrot'), ('two', 2, 'cheese'))}, ("one:1,carrot/two:2,cheese/", "one:1,carrot/two:2,cheese/")), 
     487            'for-tag-default01': ("{% for val in values %}{{ val }}{% default %}default text{% endfor %}", {"values": [1, 2, 3]}, "123"), 
     488            'for-tag-default02': ("{% for val in values %}{{ val }}{% default %}values array empty{% endfor %}", {"values": []}, "values array empty"), 
     489            'for-tag-default03': ("{% for val in values %}{{ val }}{% default %}values array not found{% endfor %}", {}, "values array not found"), 
    487490 
    488491            ### IF TAG ################################################################