Ticket #3184: better-unordered.patch

File better-unordered.patch, 6.1 KB (added by SmileyChris, 8 years ago)

completely rewritten with tests and docs

  • django/template/defaultfilters.py

     
    355355    Recursively takes a self-nested list and returns an HTML unordered list --
    356356    WITHOUT opening and closing <ul> tags.
    357357
    358     The list is assumed to be in the proper format. For example, if ``var`` contains
    359     ``['States', [['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]]``,
     358    The list is assumed to be in the proper format. For example, if ``var``
     359    contains: ``['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']]``,
    360360    then ``{{ var|unordered_list }}`` would return::
    361361
    362362        <li>States
     
    371371        </ul>
    372372        </li>
    373373    """
    374     def _helper(value, tabs):
     374    def convert_old_style_list(list_):
     375        """
     376        Converts old style lists to the new easier to understand format.
     377
     378        The old list format looked like:
     379            ['Item 1', [['Item 1.1', []], ['Item 1.2', []]]
     380
     381        And it is converted to:
     382            ['Item 1', ['Item 1.1', 'Item 1.2]]
     383        """
     384        if not isinstance(list_, (tuple, list)) or len(list_) != 2:
     385            return list_, False
     386        first_item, second_item = list_
     387        if second_item == []:
     388            return [first_item], True
     389        old_style_list = True
     390        new_second_item = []
     391        for sublist in second_item:
     392            item, old_style_list = convert_old_style_list(sublist)
     393            if not old_style_list:
     394                break
     395            new_second_item.extend(item)
     396        if old_style_list:
     397            second_item = new_second_item
     398        return [first_item, second_item], old_style_list
     399    def _helper(list_, tabs=1):
    375400        indent = u'\t' * tabs
    376         if value[1]:
    377             return u'%s<li>%s\n%s<ul>\n%s\n%s</ul>\n%s</li>' % (indent, force_unicode(value[0]), indent,
    378                 u'\n'.join([_helper(v, tabs+1) for v in value[1]]), indent, indent)
    379         else:
    380             return u'%s<li>%s</li>' % (indent, force_unicode(value[0]))
    381     return _helper(value, 1)
     401        output = []
    382402
     403        list_length = len(list_)
     404        i = 0
     405        while i < list_length:
     406            title = list_[i]
     407            sublist = ''
     408            sublist_item = None
     409            if isinstance(title, (list, tuple)):
     410                sublist_item = title
     411                title = ''
     412            elif i < list_length - 1:
     413                next_item = list_[i+1]
     414                if next_item and isinstance(next_item, (list, tuple)):
     415                    # The next item is a sub-list.
     416                    sublist_item = next_item
     417                    # We've processed the next item now too.
     418                    i += 1
     419            if sublist_item:
     420                sublist = _helper(sublist_item, tabs+1)
     421                sublist = '\n%s<ul>\n%s\n%s</ul>\n%s' % (indent, sublist,
     422                                                         indent, indent)
     423            output.append('%s<li>%s%s</li>' % (indent, force_unicode(title),
     424                                               sublist))
     425            i += 1
     426        return '\n'.join(output)
     427    value, converted = convert_old_style_list(value)
     428    return _helper(value)
     429
    383430###################
    384431# INTEGERS        #
    385432###################
  • docs/templates.txt

     
    12951295Recursively takes a self-nested list and returns an HTML unordered list --
    12961296WITHOUT opening and closing <ul> tags.
    12971297
     1298**Changed in Django development version**
     1299
     1300The format accepted by ``unordered_list`` has changed to an easier to
     1301understand format.
     1302
    12981303The list is assumed to be in the proper format. For example, if ``var`` contains
    1299 ``['States', [['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]]``,
    1300 then ``{{ var|unordered_list }}`` would return::
     1304``['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']]``, then
     1305``{{ var|unordered_list }}`` would return::
    13011306
    13021307    <li>States
    13031308    <ul>
     
    13111316    </ul>
    13121317    </li>
    13131318
     1319Note: the previous more restrictive and verbose format is still supported:
     1320``['States', [['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]]``,
     1321
    13141322upper
    13151323~~~~~
    13161324
  • tests/regressiontests/defaultfilters/tests.py

     
    266266>>> slice_(u'abcdefg', u'0::2')
    267267u'aceg'
    268268
     269>>> unordered_list([u'item 1', u'item 2'])
     270u'\t<li>item 1</li>\n\t<li>item 2</li>'
     271
     272>>> unordered_list([u'item 1', [u'item 1.1']])
     273u'\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1</li>\n\t</ul>\n\t</li>'
     274
     275>>> unordered_list([u'item 1', [u'item 1.1', u'item1.2'], u'item 2'])
     276u'\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1</li>\n\t\t<li>item1.2</li>\n\t</ul>\n\t</li>\n\t<li>item 2</li>'
     277
     278>>> unordered_list([u'item 1', [u'item 1.1', [u'item 1.1.1', [u'item 1.1.1.1']]]])
     279u'\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1\n\t\t<ul>\n\t\t\t<li>item 1.1.1\n\t\t\t<ul>\n\t\t\t\t<li>item 1.1.1.1</li>\n\t\t\t</ul>\n\t\t\t</li>\n\t\t</ul>\n\t\t</li>\n\t</ul>\n\t</li>'
     280
     281>>> unordered_list(['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']])
     282u'\t<li>States\n\t<ul>\n\t\t<li>Kansas\n\t\t<ul>\n\t\t\t<li>Lawrence</li>\n\t\t\t<li>Topeka</li>\n\t\t</ul>\n\t\t</li>\n\t\t<li>Illinois</li>\n\t</ul>\n\t</li>'
     283
     284# Old format for unordered lists should still work
    269285>>> unordered_list([u'item 1', []])
    270286u'\t<li>item 1</li>'
    271287
     
    275291>>> unordered_list([u'item 1', [[u'item 1.1', []], [u'item 1.2', []]]])
    276292u'\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1</li>\n\t\t<li>item 1.2</li>\n\t</ul>\n\t</li>'
    277293
     294>>> unordered_list(['States', [['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]])
     295u'\t<li>States\n\t<ul>\n\t\t<li>Kansas\n\t\t<ul>\n\t\t\t<li>Lawrence</li>\n\t\t\t<li>Topeka</li>\n\t\t</ul>\n\t\t</li>\n\t\t<li>Illinois</li>\n\t</ul>\n\t</li>'
     296
    278297>>> add(u'1', u'2')
    2792983
    280299
Back to Top