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
- 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
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:
create a templatetags directory in your application folder (not project)
Add an
__init__.py
file in your templatetags directoryCreate 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:
)Add the following to the top of the file:
from django import template
register = template.Library()
Change
Nodes
totemplate.Nodes
and all instances ofNodeList()
totemplate.NodeList()
In your django template page use
{% load imageTable %}
where 'imageTable' is the name of the file you created in step oneNow everything should be solid
#
cannot make it work for me.
#
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)
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:
#
Please login first before commenting.