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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132 | from django.template import NodeList,Template,Context,Variable,Library,Node,Variable,loader
from django.template import TemplateSyntaxError,VariableDoesNotExist
import math
register=Library()
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 not values: values=[]
if not hasattr(values,'__len__'):values=list(values)
len_values=len(values)
innernodelist=NodeList()
totalrows=int(math.ceil(float(len_values)/float(self.cols)))
rowcount=0
for i, item in enumerate(values):
loopctx={
'counter0':i,
'counter':i+1,
'rowcounter0':(i/self.cols),
'rowcounter':((i/self.cols)+1),
'firstrow':(i<self.cols),
'lastrow':(i>len_values-self.cols),
'firstcell':(i==0),
'lastcell':(i==len_values-1),
'evencol':(i%2)==0,
'oddcol':(i%2)==1,
'parenttable':parenttable,
}
context[self.cellvar]=item
loopctx['oddrow']=False
loopctx['evenrow']=False
loopctx['lastcellinrow']=False
loopctx["startrow"]=False
loopctx["endrow"]=False
if totalrows==1 and i==len_values-1: loopctx['lastcellinrow']=True
elif i==(len_values-1): loopctx['lastcellinrow']=True
if i % self.cols==0:
nodelist.append(innernodelist.render(context))
innernodelist=NodeList()
loopctx["startrow"]=True
if (rowcount+1)%2==0:
loopctx["oddrow"]=False
loopctx["evenrow"]=True
else:
loopctx["oddrow"]=True
loopctx["evenrow"]=False
elif (i+1) % self.cols==0:
loopctx['lastcellinrow']=True
loopctx["endrow"]=True
rowcount+=1
context['table']=loopctx
for node in self.cellnodes: innernodelist.append(node.render(context))
if innernodelist and len(innernodelist)>0: nodelist.append(innernodelist.render(context))
context.pop()
return nodelist.render(context)
@register.tag(name="table")
def do_table(parser,token):
"""
Tag to help rendering tables. Replicates the django for tag,
but add's in more helpers specific to tables.
{{table.counter0}}
{{table.counter}}
{{table.rowcounter0}}
{{table.rowcounter}}
{{table.startrow}}
{{table.endrow}}
{{table.oddrow}}
{{table.evenrow}}
{{table.firstrow}}
{{table.lastrow}}
{{table.firstcell}}
{{table.lastcell}}
{{table.lastcellinrow}}
{{table.evencol}}
{{table.oddcol}}
{{table.parenttable}}
EX:
(this is a some what more complicated example, which
hopefully illustrates this tags use better):
<table width="100%">
{% table genre artist.genres.all 5 %}
{% if table.startrow %}
{% if table.oddrow %}
<tr class="highlight">
{% else %}
<tr>
{% endif %}
{% endif %}
{% if table.lastcellinrow %}
<td class="{% if table.oddrow %}highlightableCell {% endif %}cellAutoAdjust removeableGenre">
{% else %}
<td class="{% if table.oddrow %}highlightableCell {% endif %}left cellAutoAdjust removeableGenre">
{% endif %}
<div class="options displayNone"></div>
{{genre.name}}
</td>
{% if table.endrow %}
</tr>
{% endif %}
{% endtable %}
</table>
"""
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)
|
Comments
Thanks for the tag. I find it very useful.
I can do this
and it works great. Is there a simple way to do this
where ctext['num_cols']=5 ? I have tried as above, as {{num_cols}}, setting self.cols=int(cols) in the init fcn, etc., but to no avail.
The background is that I manipulate the array in a way that depends on the number of columns (I arrange the names alphabetically from up to down instead of from left to right) and I don't want the number of columns to be hard coded in two places.
#
{% if table.endrow %} [tr tag] {%a endif %}
Sometimes this works wrong for last row (for example in table with 2 rows and 9 cells)
To fix it, just replace 54 line
to
#