Table

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
class TableNode(Node):
    def __init__(self, cellvar, sequence, cols, cellnodes):
        self.cellvar = cellvar
        self.sequence = sequence
        self.cols = cols
        self.cellnodes = cellnodes
        
    def __iter__(self):
        for node in self.cellnodes:
            yield node
        
    def get_nodes_by_type(self, nodetype):
        nodes = []
        if isinstance(self, nodetype):
            nodes.append(self)
        nodes.extend(self.cellnodes.get_nodes_by_type(nodetype))
        return nodes
    
    def render(self, context):
        nodelist = NodeList()
        if context.has_key('parenttable'):
            parenttable = context['parenttable']
        else:
            parenttable = {}
        context.push()
        try:
            values = self.sequence.resolve(context, True)
        except VariableDoesNotExist:
            values = []
        if values is None:
            values = []
        if not hasattr(values, '__len__'):
            values = list(values)
        len_values = len(values)
      
        innernodelist = NodeList()
        for i, item in enumerate(values):
            loopctx = {
                # shortcuts for current loop iteration number
                'counter0': i,
                'counter': i+1,
                'rowcounter0': i / self.cols,
                'rowcounter': (i/self.cols) + 1,
                'even': (i % 2 == 0),
                # boolean values designating first and last items
                'firstrow': (i < self.cols),
                'lastrow': (i > len_values - self.cols),
                'firstcell': (i == 0),
                'lastcell': (i == len_values - 1),
                'parenttable': parenttable,
            }
            context[self.cellvar] = item
            loopctx["startrow"] = False
            loopctx["endrow"] = False            
            if i % self.cols == 0:
                nodelist.append(innernodelist.render(context))
                innernodelist = NodeList()
                loopctx["startrow"] = True
            elif (i + 1) % self.cols == 0:
                loopctx["endrow"] = True

            context['table'] = loopctx            
            for node in self.cellnodes:
                innernodelist.append(node.render(context))
        if innernodelist != None and len(innernodelist) > 0:
            nodelist.append(innernodelist.render(context))
        print "Done rendering table"
        context.pop()
        return nodelist.render(context)

def do_table(parser,token):
    bits = token.contents.split()
    cellvar = bits[1]
    sequence = parser.compile_filter(bits[2])
    cols = int(bits[3])
    cellnodes = parser.parse(('endtable',))
    parser.delete_first_token()
    return TableNode(cellvar, sequence, cols, cellnodes)

register.tag("table", do_table)

##Sample usage:
    	<table>
    	{% table pic gallery_pics 5 %}
    	   {% if table.firstcell %}<tbody>{% endif %}
    	   {% if table.startrow %}<tr>{% endif %}
    	   <td>{{pic.filename}}</td>
    	   {% if table.endrow %}</tr>{% endif %}
    	   {% if table.lastcell %}</tbody>{% endif %}
    	{% endtable %}
    	</table>

More like this

  1. (Almost) Single table polymorphism in Django by julkiewicz 3 years ago
  2. custom sql without table names by robharvey 6 years, 11 months ago
  3. Group sequence into rows and columns for a TABLE by davidwtbuxton 3 years, 1 month ago
  4. Cleanup dirty HTML from a WYSIWYG editor by denis 4 years, 10 months ago
  5. Sort Table Headers by insin 6 years, 9 months ago

Comments

Josh (on July 18, 2007):

Hey there,

I spent a little time getting this code integrated into my project - and thought I might share the changes I needed to perform to get it working - for all those copy-and-pasters (like myself).

I did have one question for anyone who might be able to answer it. I haven't spent much time modifying this code - however I noticed that it only creates as many td tags as you have elements in your sequence. For instance - if I have 6 elements and have set the maximum columns set to 5 - how do I get the second row to print those extra 4 td tags that are missing from the element? It doesn't seem to be affecting anything negatively right now - however I'm not sure it's valid.

Anyway, to get this code running:

  1. create a templatetags directory in your application folder (not project)

  2. Add an __init__.py file in your templatetags directory

  3. Create a new .py file in the templatetags directory with the above code in it (comment out the html in the above code - after ##Sample usage:)

  4. Add the following to the top of the file:

    from django import template

    register = template.Library()

  5. Change Nodes to template.Nodes and all instances of NodeList() to template.NodeList()

  6. In your django template page use {% load imageTable %} where 'imageTable' is the name of the file you created in step one

Now everything should be solid

#

tupopo (on September 11, 2007):

cannot make it work for me.

#

elgreengeeto (on December 1, 2008):

As a quick, simple way to make a table I added a custom template filter for modulo of an integer:

(add to .../mysite/myapp/templatetags/myapp_tags.py)

from django import template
register = template.Library()

@register.filter
def mod(value, arg):
    return value % arg

and then it's very easy in the template to make a table with n elements per row with a simple for loop by seeing if ( for_loop.counter modulo n ) is zero, and if so make a new table row:

{% load pictures_tags %} #(<-this loads your custom filter)

<table>
<tr>
{% for pic in pic_list %}
  <td>
  <img src="{{pic.source}}" />
  </td>
  {% if not forloop.counter|mod:5 %}
    </tr><tr>
  {% endif %}
{% endfor %}
</tr>
</table>

#

(Forgotten your password?)