Login

Template range loop

Author:
nfg
Posted:
January 28, 2010
Language:
Python
Version:
1.1
Score:
0 (after 0 ratings)

This tag is meant to mimic the python use of range in a for-loop: 'for i in range(start, end, step)'. It is implemented like a loop and it takes both variable names from the context and constant integers as arguments.

Syntax:
{% range end as i %}
  {{ i }}
{% endrange %}
{% range start:end as i %}
  {{ i }}
{% endrange %}
{% range start:step:end as i %}
  {{ i }}
{% endrange %}
  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
from django.template import Library, Node, NodeList, Variable,\
    TemplateSyntaxError, VariableDoesNotExist

register = Library()

class RangeNode(Node):
    def __init__(self, var_name, start, end, step, nodelist_loop):
        self.var_name = var_name
        self.nodelist_loop = nodelist_loop

        try:
            self.start = int(start)
        except ValueError:
            self.start = Variable(start)

        try:
            self.end = int(end)
        except ValueError:
            self.end = Variable(end)

        try:
            self.step = int(step)
        except ValueError:
            self.step = Variable(step)

    def __iter__(self):
        for node in self.nodelist_loop:
            yield node
   
    def render(self, context):
        nodelist = NodeList()

        context.push()
        try:
            start = self.start.resolve(context)
        except VariableDoesNotExist:
            return ''
        except AttributeError:
            start = self.start

        try:
            end = self.end.resolve(context)
        except VariableDoesNotExist:
            return ''
        except AttributeError:
            end = self.end

        try:
            step = self.step.resolve(context)
        except VariableDoesNotExist:
            return ''
        except AttributeError:
            step = self.step

        for i in xrange(start, end, step):
            context[self.var_name] = i

            for node in self.nodelist_loop:
                nodelist.append(node.render(context))

        context.pop()
        return nodelist.render(context)

def do_range(parser, token):
    """
    Work much like forloop with a range.
    Takes both variables and constant integers.
    
    Syntax:
    {% range end as i %}
      {{ i }}
    {% endrange %}
    {% range start:end as i %}
      {{ i }}
    {% endrange %}
    {% range start:step:end as i %}
      {{ i }}
    {% endrange %}

    """

    bits = token.split_contents()
    if len(bits) != 4 or bits[2] != 'as':
        raise TemplateSyntaxError(
            "%r expected format is '[start:][step:]end as name'" % bits[0]
        )
        
    var_name = bits[3]

    rangebits = bits[1].split(':')
    if len(rangebits) == 1:
        start = 0
        end = rangebits[0]
        step = 1
    elif len(rangebits) == 2:
        start = rangebits[0]
        end = rangebits[1]
        step = 1
    elif len(rangebits) == 3:
        start = rangebits[0]
        step = rangebits[1]
        end = rangebits[2]
        
    nodelist = parser.parse(('endrange',))
    parser.delete_first_token()
    return RangeNode(var_name, start, end, step, nodelist)
do_range = register.tag('range', do_range)

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 2 months ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 2 months, 1 week ago
  3. Serializer factory with Django Rest Framework by julio 9 months, 1 week ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 9 months, 4 weeks ago
  5. Help text hyperlinks by sa2812 10 months, 3 weeks ago

Comments

Please login first before commenting.