Разбиение объектов на “равные” части

Предлагаю вашему вниманию небольшой снипет, который мы написали, когда понадобилось сделать вывод объектов по колонкам.

  1. from django import template
  2.  
  3.  
  4. register = template.Library()
  5.  
  6.  
  7. class SplitObjectsNode(template.Node):
  8.     def __init__(self, objects, list):
  9.         self._objects = template.Variable(objects)
  10.         self._list = list
  11.  
  12.     def render(self, context):
  13.         import math
  14.         columns_count = len(self._list)
  15.         objects = self._objects.resolve(context)
  16.  
  17.         for item in self._list:
  18.             context[item] = []
  19.  
  20.         if len(objects) == 0:
  21.             return
  22.  
  23.         dec = float(len(list(objects))) / columns_count
  24.         mid = int(math.ceil(dec))
  25.         pass_part = len(list(objects)) % columns_count
  26.         count_full_cols = columns_count – pass_part
  27.  
  28.         idx = 0
  29.         index = 0
  30.         for item in self._list:
  31.             step = mid
  32.             if idx >= pass_part and pass_part != 0:
  33.                 step = mid – 1
  34.             context[item] = objects[index: step + index]
  35.             index += step
  36.             idx += 1
  37.         return
  38.  
  39.  
  40. @register.tag
  41. def split_objects(parser, token):
  42.     """                                                                                                                                                                                                      
  43.    Split content of the objects to equal parts. Number of parts is a count of passed arguments to tag.                                                                                                      
  44.                                                                                                                                                                                                            
  45.    Example:                                                                                                                                                                                                
  46.    {% split_objects objects col1 col2 col3 %}                                                                                                                                                              
  47.    <table><tr><td>                                                                                                                                                                                          
  48.    {% for item in col1 %} {{ item.title }} {% endfor %}                                                                                                                                                    
  49.    </td><td>                                                                                                                                                                                                
  50.    {% for item in col2 %} {{ item.title }} {% endfor %}                                                                                                                                                    
  51.    </td><td>                                                                                                                                                                                                
  52.    {% for item in col3 %} {{ item.title }} {% endfor %}                                                                                                                                                    
  53.    </td></tr></table>                                                                                                                                                                                      
  54.    """
  55.     parts = token.contents.split()
  56.     if len(parts) < 3:
  57.         raise template.TemplateSyntaxError, "Tag should get at the least 3 arguments. Example usage is {% split_objects objects col1 col2 %}"
  58.  
  59.     tagname = parts.pop(0)
  60.     objects = parts.pop(0)
  61.     return SplitObjectsNode(objects, parts)