开发者

Howto add properties to the output of unordered_list?

开发者 https://www.devze.com 2023-01-29 22:42 出处:网络
I am using an unordered_list tag in django. I have the following list: foo = [\'A\', [\'B\', \'C\', \'D\'], \'E\']

I am using an unordered_list tag in django.

I have the following list:

foo = ['A', ['B', 'C', 'D'], 'E']

And the following tag:

{{ foo|unordered_list }}

Which produces, as expected the following:

开发者_运维百科<li>A
    <ul>
            <li>B</li>
            <li>C</li>
            <li>D</li>
    </ul>
</li>
<li>E</li>

What I would like to do is to add id and class properties to each "li" node. I understand that I can do it in JavaScript, or implement my own template tag in django. But I wanted to ask first. May be there already exists an easy build-in way to do it in django template?


As you can see in the source, the <li> is hardcoded so you can't do it without creating your own templatefilter.

def unordered_list(value, autoescape=None):                                                                                                                                                                                                                                                                                 
    """                                                                                                                                                                                                                                                                                                                     
    Recursively takes a self-nested list and returns an HTML unordered list --                                                                                                                                                                                                                                              
    WITHOUT opening and closing <ul> tags.                                                                                                                                                                                                                                                                                  

    The list is assumed to be in the proper format. For example, if ``var``                                                                                                                                                                                                                                                 
    contains: ``['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']]``,                                                                                                                                                                                                                                               
    then ``{{ var|unordered_list }}`` would return::                                                                                                                                                                                                                                                                        

        <li>States                                                                                                                                                                                                                                                                                                          
        <ul>                                                                                                                                                                                                                                                                                                                
                <li>Kansas                                                                                                                                                                                                                                                                                                  
                <ul>                                                                                                                                                                                                                                                                                                        
                        <li>Lawrence</li>                                                                                                                                                                                                                                                                                   
                        <li>Topeka</li>                                                                                                                                                                                                                                                                                     
                </ul>                                                                                                                                                                                                                                                                                                       
                </li>                                                                                                                                                                                                                                                                                                       
                <li>Illinois</li>                                                                                                                                                                                                                                                                                           
        </ul>                                                                                                                                                                                                                                                                                                               
        </li>                                                                                                                                                                                                                                                                                                               
    """                                                                                                                                                                                                                                                                                                                     
    if autoescape:                                                                                                                                                                                                                                                                                                          
        from django.utils.html import conditional_escape                                                                                                                                                                                                                                                                    
        escaper = conditional_escape                                                                                                                                                                                                                                                                                        
    else:                                                                                                                                                                                                                                                                                                                   
        escaper = lambda x: x                                                                                                                                                                                                                                                                                               
    def convert_old_style_list(list_):                                                                                                                                                                                                                                                                                      
        """                                                                                                                                                                                                                                                                                                                 
        Converts old style lists to the new easier to understand format.                                                                                                                                                                                                                                                    

        The old list format looked like:                                                                                                                                                                                                                                                                                    
            ['Item 1', [['Item 1.1', []], ['Item 1.2', []]]                                                                                                                                                                                                                                                                 

        And it is converted to:                                                                                                                                                                                                                                                                                             
            ['Item 1', ['Item 1.1', 'Item 1.2]]                                                                                                                                                                                                                                                                             
        """                                                                                                                                                                                                                                                                                                                 
        if not isinstance(list_, (tuple, list)) or len(list_) != 2:                                                                                                                                                                                                                                                         
            return list_, False                                                                                                                                                                                                                                                                                             
        first_item, second_item = list_                                                                                                                                                                                                                                                                                     
        if second_item == []:                                                                                                                                                                                                                                                                                               
            return [first_item], True                                                                                                                                                                                                                                                                                       
        old_style_list = True                                                                                                                                                                                                                                                                                               
        new_second_item = []                                                                                                                                                                                                                                                                                                
        for sublist in second_item:                                                                                                                                                                                                                                                                                         
            item, old_style_list = convert_old_style_list(sublist)                                                                                                                                                                                                                                                          
            if not old_style_list:                                                                                                                                                                                                                                                                                          
                break                                                                                                                                                                                                                                                                                                       
            new_second_item.extend(item)                                                                                                                                                                                                                                                                                    
        if old_style_list:                                                                                                                                                                                                                                                                                                  
            second_item = new_second_item                                                                                                                                                                                                                                                                                   
        return [first_item, second_item], old_style_list                                                                                                                                                                                                                                                                    
    def _helper(list_, tabs=1):                                                                                                                                                                                                                                                                                             
        indent = u'\t' * tabs                                                                                                                                                                                                                                                                                               
        output = []                                                                                                                                                                                                                                                                                                         

        list_length = len(list_)                                                                                                                                                                                                                                                                                            
        i = 0                                                                                                                                                                                                                                                                                                               
        while i < list_length:                                                                                                                                                                                                                                                                                              
            title = list_[i]                                                                                                                                                                                                                                                                                                
            sublist = ''                                                                                                                                                                                                                                                                                                    
            sublist_item = None                                                                                                                                                                                                                                                                                             
            if isinstance(title, (list, tuple)):                                                                                                                                                                                                                                                                            
                sublist_item = title                                                                                                                                                                                                                                                                                        
                title = ''                                                                                                                                                                                                                                                                                                  
            elif i < list_length - 1:                                                                                                                                                                                                                                                                                       
                next_item = list_[i+1]                                                                                                                                                                                                                                                                                      
                if next_item and isinstance(next_item, (list, tuple)):                                                                                                                                                                                                                                                      
                    # The next item is a sub-list.                                                                                                                                                                                                                                                                          
                    sublist_item = next_item                                                                                                                                                                                                                                                                                
                    # We've processed the next item now too.                                                                                                                                                                                                                                                                
                    i += 1                                                                                                                                                                                                                                                                                                  
            if sublist_item:                                                                                                                                                                                                                                                                                                
                sublist = _helper(sublist_item, tabs+1)                                                                                                                                                                                                                                                                     
                sublist = '\n%s<ul>\n%s\n%s</ul>\n%s' % (indent, sublist,                                                                                                                                                                                                                                                   
                                                         indent, indent)                                                                                                                                                                                                                                                    
            output.append('%s<li>%s%s</li>' % (indent,                                                                                                                                                                                                                                                                      
                    escaper(force_unicode(title)), sublist))                                                                                                                                                                                                                                                                
            i += 1                                                                                                                                                                                                                                                                                                          
        return '\n'.join(output)                                                                                                                                                                                                                                                                                            
    value, converted = convert_old_style_list(value)                                                                                                                                                                                                                                                                        
    return mark_safe(_helper(value))                                                                                                                                                                                                                                                                                        
unordered_list.is_safe = True                                                                                                                                                                                                                                                                                               
unordered_list.needs_autoescape = True

It should be fairly easy to rewrite the filter to add id/class support though, depending on how you want it to work.

0

精彩评论

暂无评论...
验证码 换一张
取 消