- Author:
- bl4th3rsk1t3
- Posted:
- June 1, 2009
- Language:
- Python
- Version:
- 1.0
- Score:
- 3 (after 3 ratings)
This table tag helps with render tables, which can be fairly complex.
I updated the previous table tag (296).
I added support for oddrow,evenrow,lastcellinrow,oddcol,evencol. And made a few minor adjustments to syntax formatting, and some non needed if conditionals
These are all of the supported variables available in the context
{{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}}
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)
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
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
#
Please login first before commenting.