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 | # based on: http://www.djangosnippets.org/snippets/1926/
from django.template import Library, Node, TemplateSyntaxError
register = Library()
class RangeNode(Node):
def __init__(self, parser, range_args, context_name):
self.template_parser = parser
self.range_args = range_args
self.context_name = context_name
def render(self, context):
resolved_ranges = []
for arg in self.range_args:
compiled_arg = self.template_parser.compile_filter(arg)
resolved_ranges.append(compiled_arg.resolve(context, ignore_failures=True))
context[self.context_name] = range(*resolved_ranges)
return ""
@register.tag
def mkrange(parser, token):
"""
Accepts the same arguments as the 'range' builtin and creates
a list containing the result of 'range'.
Syntax:
{% mkrange [start,] stop[, step] as context_name %}
For example:
{% mkrange 5 10 2 as some_range %}
{% for i in some_range %}
{{ i }}: Something I want to repeat\n
{% endfor %}
Produces:
5: Something I want to repeat
7: Something I want to repeat
9: Something I want to repeat
"""
tokens = token.split_contents()
fnctl = tokens.pop(0)
def error():
raise TemplateSyntaxError, "%s accepts the syntax: {%% %s [start,] " +\
"stop[, step] as context_name %%}, where 'start', 'stop' " +\
"and 'step' must all be integers." %(fnctl, fnctl)
range_args = []
while True:
if len(tokens) < 2:
error()
token = tokens.pop(0)
if token == "as":
break
range_args.append(token)
if len(tokens) != 1:
error()
context_name = tokens.pop()
return RangeNode(parser, range_args, context_name)
|
Comments
Note that the created range can only be used once in Python 3. It will needl to be wrapped in a list() to be reused.
#