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 | # table.py -- tag and filter implementation
from django import template
from django.shortcuts import render_to_response
from django.template.loader import get_template
def reshape( lst, ncols, nrows, horiz=True ):
"""Change shape of list lst (like APL, J, K, NumPy).
Return list of lists: ncols x nrows. horiz - is the
table direction (horizontal or vertical if horiz is
False). Empty cells will be with ''
"""
if not ncols and not nrows: return lst
w = ncols or len(lst)/nrows + (1 if len(lst)%nrows else 0)
h = nrows or len(lst)/ncols + (1 if len(lst)%ncols else 0)
if horiz:
flatten = lambda irow, icol: icol + irow*w
else:
flatten = lambda irow, icol: irow + icol*h
rows = []
for irow in range( h ):
col = []
for icol in range( w ):
iflat = flatten( irow, icol )
el = '' if iflat >= len(lst) else lst[iflat]
col.append( el )
rows.append( col )
return rows
register = template.Library()
@register.tag
def table( parser, token ):
""" Push in context 'table_obj' object - list of lists, result
of reshape function (see it)"""
try:
# lst - name of the list in the context, shape is string like 'H:4x?'|'V:2x2'|'?x3'
# 'H' - horiz direction, 'V' - vertical direction, '?' - computable size, digit -
# fixed size (see reshape function!)
tag, lst, shape = token.split_contents()
except ValueError:
sx = 'tag %r requires two arguments'%token.contents[0]
raise template.TemplateSyntaxError( sx )
shape = shape[1:-1].upper() # cut .. from ".."
if shape.startswith( 'V:' ):
horiz = False
shape = shape[2:]
elif shape.startswith( 'H:' ):
horiz = True
shape = shape[2:]
else:
horiz = True
w,h = shape.split( 'X' )
w = None if w == '?' else int(w)
h = None if h == '?' else int(h)
if not h and not w:
raise template.TemplateSyntaxError( 'only one axis may be unknown (?)' )
nodes = parser.parse( ('endtable',) )
parser.delete_first_token()
return TableNode( nodes, lst, w, h, horiz )
class TableNode( template.Node ):
def __init__( self, nodes, lst, w, h, horiz ):
self.nodes = nodes
self.lst = lst
self.w = w
self.h = h
self.horiz = horiz
def render( self, context ):
# get list from context by it's name
res = reshape( context[self.lst], self.w, self.h, self.horiz )
context.push()
context[ 'table_obj' ] = res
txt = self.nodes.render( context )
context.pop()
return txt
@register.filter
def flatindex( forloop ):
"""Existed in the nested loops return flat index
(index of flat list). For example:
like in C N-th dimension array may look like
flat array with ONE, flat index. This tag generate
this flat index for nested loops in django template (see nested {% for...%})"""
loop = forloop
level = 0
ret = 0
nestedlen = 1
while True:
if level == 0:
ret += loop['counter0']
# length of current level * size of previous levels is
# "weight" of ranking level. Ranking level add
# nestedlen to flatindex if move by 1 (like hypercube).
nestedlen *= loop['counter0'] + loop['revcounter0'] + 1
else:
ret += loop['counter0']*nestedlen
# go to next-up level
parentloop = loop.get('parentloop', None)
if parentloop:
loop = parentloop
else:
break
level += 1
return ret
|
Comments