1 | from django.utils.translation import ungettext, ugettext as _
|
---|
2 | from django.utils.encoding import force_unicode
|
---|
3 | from django import template
|
---|
4 | from django.template import defaultfilters
|
---|
5 | from django.template import Node, Variable
|
---|
6 | from django.conf import settings
|
---|
7 | from itertools import cycle as itertools_cycle
|
---|
8 |
|
---|
9 | register = template.Library()
|
---|
10 |
|
---|
11 |
|
---|
12 |
|
---|
13 | class SafeCycleNode(Node):
|
---|
14 | def __init__(self, cyclevars, variable_name=None):
|
---|
15 | self.cyclevars = cyclevars
|
---|
16 | self.cycle_iter = itertools_cycle(cyclevars)
|
---|
17 | self.variable_name = variable_name
|
---|
18 |
|
---|
19 | def render(self, context):
|
---|
20 | if context.has_key('forloop'):
|
---|
21 | if not context.get(self):
|
---|
22 | context[self] = True
|
---|
23 | self.cycle_iter = itertools_cycle(self.cyclevars)
|
---|
24 | value = self.cycle_iter.next()
|
---|
25 | value = Variable(value).resolve(context)
|
---|
26 | if self.variable_name:
|
---|
27 | context[self.variable_name] = value
|
---|
28 | return value
|
---|
29 |
|
---|
30 |
|
---|
31 |
|
---|
32 | #@register.tag
|
---|
33 | def safe_cycle(parser, token):
|
---|
34 | """
|
---|
35 | Cycles among the given strings each time this tag is encountered.
|
---|
36 |
|
---|
37 | Within a loop, cycles among the given strings each time through
|
---|
38 | the loop::
|
---|
39 |
|
---|
40 | {% for o in some_list %}
|
---|
41 | <tr class="{% cycle 'row1' 'row2' %}">
|
---|
42 | ...
|
---|
43 | </tr>
|
---|
44 | {% endfor %}
|
---|
45 |
|
---|
46 | Outside of a loop, give the values a unique name the first time you call
|
---|
47 | it, then use that name each sucessive time through::
|
---|
48 |
|
---|
49 | <tr class="{% cycle 'row1' 'row2' 'row3' as rowcolors %}">...</tr>
|
---|
50 | <tr class="{% cycle rowcolors %}">...</tr>
|
---|
51 | <tr class="{% cycle rowcolors %}">...</tr>
|
---|
52 |
|
---|
53 | You can use any number of values, seperated by spaces. Commas can also
|
---|
54 | be used to separate values; if a comma is used, the cycle values are
|
---|
55 | interpreted as literal strings.
|
---|
56 | """
|
---|
57 |
|
---|
58 | # Note: This returns the exact same node on each {% cycle name %} call;
|
---|
59 | # that is, the node object returned from {% cycle a b c as name %} and the
|
---|
60 | # one returned from {% cycle name %} are the exact same object. This
|
---|
61 | # shouldn't cause problems (heh), but if it does, now you know.
|
---|
62 | #
|
---|
63 | # Ugly hack warning: this stuffs the named template dict into parser so
|
---|
64 | # that names are only unique within each template (as opposed to using
|
---|
65 | # a global variable, which would make cycle names have to be unique across
|
---|
66 | # *all* templates.
|
---|
67 |
|
---|
68 | args = token.split_contents()
|
---|
69 |
|
---|
70 | if len(args) < 2:
|
---|
71 | raise TemplateSyntaxError("'cycle' tag requires at least two arguments")
|
---|
72 |
|
---|
73 | if ',' in args[1]:
|
---|
74 | # Backwards compatibility: {% cycle a,b %} or {% cycle a,b as foo %}
|
---|
75 | # case.
|
---|
76 | args[1:2] = ['"%s"' % arg for arg in args[1].split(",")]
|
---|
77 |
|
---|
78 | if len(args) == 2:
|
---|
79 | # {% cycle foo %} case.
|
---|
80 | name = args[1]
|
---|
81 | if not hasattr(parser, '_namedCycleNodes'):
|
---|
82 | raise TemplateSyntaxError("No named cycles in template."
|
---|
83 | " '%s' is not defined" % name)
|
---|
84 | if not name in parser._namedCycleNodes:
|
---|
85 | raise TemplateSyntaxError("Named cycle '%s' does not exist" % name)
|
---|
86 | return parser._namedCycleNodes[name]
|
---|
87 |
|
---|
88 | if len(args) > 4 and args[-2] == 'as':
|
---|
89 | name = args[-1]
|
---|
90 | node = SafeCycleNode(args[1:-2], name)
|
---|
91 | if not hasattr(parser, '_namedCycleNodes'):
|
---|
92 | parser._namedCycleNodes = {}
|
---|
93 | parser._namedCycleNodes[name] = node
|
---|
94 | else:
|
---|
95 | node = SafeCycleNode(args[1:])
|
---|
96 | return node
|
---|
97 | safe_cycle = register.tag(safe_cycle)
|
---|