Login

Table

Author:
Samus
Posted:
June 26, 2007
Language:
Python
Version:
.96
Score:
2 (after 2 ratings)

This is rough code that will allow you to create a table using a sequence. It is based on the for loop tag in django template. It works basically the same except that certain variables are set based on what cell is being rendered. The tag itself does not output any html at all. This allows for simple code and very flexible creation of nice tables/grids. Enjoy

 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. Template tag - list punctuation for a list of items by shapiromatron 10 months, 1 week ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 2 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
  5. Help text hyperlinks by sa2812 1 year, 6 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>

#

Please login first before commenting.