Django

Code

Ticket #6398: add_default_to_for.4.diff

File add_default_to_for.4.diff, 5.6 kB (added by jezdez, 10 months ago)

fifth implementation with optional nodelist_default, including documentation and tests.

  • django/template/defaulttags.py

    old new  
    8484        return u'' 
    8585 
    8686class ForNode(Node): 
    87     def __init__(self, loopvars, sequence, is_reversed, nodelist_loop): 
     87    def __init__(self, loopvars, sequence, is_reversed, nodelist_loop, nodelist_default=None): 
    8888        self.loopvars, self.sequence = loopvars, sequence 
    8989        self.is_reversed = is_reversed 
    9090        self.nodelist_loop = nodelist_loop 
     91        if nodelist_default is None: 
     92            self.nodelist_default = NodeList() 
     93        else: 
     94            self.nodelist_default = nodelist_default 
    9195 
    9296    def __repr__(self): 
    9397        reversed_text = self.is_reversed and ' reversed' or '' 
     
    98102    def __iter__(self): 
    99103        for node in self.nodelist_loop: 
    100104            yield node 
     105        for node in self.nodelist_default: 
     106            yield node 
    101107 
    102108    def get_nodes_by_type(self, nodetype): 
    103109        nodes = [] 
    104110        if isinstance(self, nodetype): 
    105111            nodes.append(self) 
    106112        nodes.extend(self.nodelist_loop.get_nodes_by_type(nodetype)) 
     113        nodes.extend(self.nodelist_default.get_nodes_by_type(nodetype)) 
    107114        return nodes 
    108115 
    109116    def render(self, context): 
    110         nodelist = NodeList() 
    111117        if 'forloop' in context: 
    112118            parentloop = context['forloop'] 
    113119        else: 
     
    122128        if not hasattr(values, '__len__'): 
    123129            values = list(values) 
    124130        len_values = len(values) 
     131        if len_values < 1: 
     132            return self.nodelist_default.render(context) 
     133        nodelist = NodeList() 
    125134        if self.is_reversed: 
    126135            values = reversed(values) 
    127136        unpack = len(self.loopvars) > 1 
     
    594603            {{ key }}: {{ value }} 
    595604        {% endfor %} 
    596605 
     606    The ``for`` tag can take an optional ``{% default %}`` clause that will 
     607    be displayed if the given array is empty or could not be found:: 
     608 
     609        <ul> 
     610        {% for athlete in athlete_list %} 
     611            <li>{{ athlete.name }}</li> 
     612        {% default %} 
     613            <li>Sorry, no athlete in this list!</li> 
     614        {% endfor %} 
     615        <ul> 
     616 
    597617    The for loop sets a number of variables available within the loop: 
    598618 
    599619        ==========================  ================================================ 
     
    630650                                      " %s" % token.contents) 
    631651 
    632652    sequence = parser.compile_filter(bits[in_index+1]) 
    633     nodelist_loop = parser.parse(('endfor',)) 
    634     parser.delete_first_token() 
    635     return ForNode(loopvars, sequence, is_reversed, nodelist_loop) 
     653    nodelist_loop = parser.parse(('default', 'endfor',)) 
     654    token = parser.next_token() 
     655    if token.contents == 'default': 
     656        nodelist_default = parser.parse(('endfor',)) 
     657        parser.delete_first_token() 
     658    else: 
     659        nodelist_default = None 
     660    return ForNode(loopvars, sequence, is_reversed, nodelist_loop, nodelist_default) 
    636661do_for = register.tag("for", do_for) 
    637662 
    638663def do_ifequal(parser, token, negate): 
  • tests/regressiontests/templates/tests.py

    old new  
    457457            'for-tag-unpack11': ("{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, ("one:1,/two:2,/", "one:1,INVALID/two:2,INVALID/")), 
    458458            '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/")), 
    459459            '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/")), 
     460            'for-tag-default01': ("{% for val in values %}{{ val }}{% default %}default text{% endfor %}", {"values": [1, 2, 3]}, "123"), 
     461            'for-tag-default02': ("{% for val in values %}{{ val }}{% default %}values array empty{% endfor %}", {"values": []}, "values array empty"), 
     462            'for-tag-default03': ("{% for val in values %}{{ val }}{% default %}values array not found{% endfor %}", {}, "values array not found"), 
    460463 
    461464            ### IF TAG ################################################################ 
    462465            'if-tag01': ("{% if foo %}yes{% else %}no{% endif %}", {"foo": True}, "yes"), 
  • docs/templates.txt

    old new  
    702702You can loop over a list in reverse by using ``{% for obj in list reversed %}``. 
    703703 
    704704**New in Django development version** 
     705 
    705706If you need to loop over a list of lists, you can unpack the values 
    706707in eachs sub-list into a set of known names. For example, if your context contains 
    707708a list of (x,y) coordinates called ``points``, you could use the following 
     
    719720        {{ key }}: {{ value }} 
    720721    {% endfor %} 
    721722 
     723**New in Django development version** 
     724 
     725The ``for`` tag can take an optional ``{% default %}`` clause that will be 
     726displayed if the given array is empty or could not be found:: 
     727 
     728    <ul> 
     729    {% for athlete in athlete_list %} 
     730        <li>{{ athlete.name }}</li> 
     731    {% default %} 
     732        <li>Sorry, no athlete in this list!</li> 
     733    {% endfor %} 
     734    <ul> 
     735 
    722736The for loop sets a number of variables available within the loop: 
    723737 
    724738    ==========================  ================================================