| 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)
|
|---|