コード例 #1
0
 def __init__(self, loopvars, sequence, is_reversed, nodelist_loop, nodelist_empty=None):
     self.loopvars, self.sequence = loopvars, sequence
     self.is_reversed = is_reversed
     self.nodelist_loop = nodelist_loop
     if nodelist_empty is None:
         self.nodelist_empty = NodeList()
     else:
         self.nodelist_empty = nodelist_empty
コード例 #2
0
    def render(self, context):
        if "forloop" in context:
            parentloop = context["forloop"]
        else:
            parentloop = {}
        context.push()
        try:
            values = self.sequence.resolve(context, True)
        except VariableDoesNotExist:
            values = []
        if values is None:
            values = []
        if not hasattr(values, "__len__"):
            values = list(values)
        len_values = len(values)
        if len_values < 1:
            context.pop()
            return self.nodelist_empty.render(context)
        nodelist = NodeList()
        if self.is_reversed:
            values = reversed(values)
        unpack = len(self.loopvars) > 1
        # Create a forloop value in the context.  We'll update counters on each
        # iteration just below.
        loop_dict = context["forloop"] = {"parentloop": parentloop}
        for i, item in enumerate(values):
            # Shortcuts for current loop iteration number.
            loop_dict["counter0"] = i
            loop_dict["counter"] = i + 1
            # Reverse counter iteration numbers.
            loop_dict["revcounter"] = len_values - i
            loop_dict["revcounter0"] = len_values - i - 1
            # Boolean values designating first and last times through loop.
            loop_dict["first"] = i == 0
            loop_dict["last"] = i == len_values - 1

            pop_context = False
            if unpack:
                # If there are multiple loop variables, unpack the item into
                # them.
                try:
                    unpacked_vars = dict(zip(self.loopvars, item))
                except TypeError:
                    pass
                else:
                    pop_context = True
                    context.update(unpacked_vars)
            else:
                context[self.loopvars[0]] = item
            # In TEMPLATE_DEBUG mode provide source of the node which
            # actually raised the exception
            if settings.TEMPLATE_DEBUG:
                for node in self.nodelist_loop:
                    try:
                        nodelist.append(node.render(context))
                    except Exception as e:
                        if not hasattr(e, "django_template_source"):
                            e.django_template_source = node.source
                        raise
            else:
                for node in self.nodelist_loop:
                    nodelist.append(node.render(context))
            if pop_context:
                # The loop variables were pushed on to the context so pop them
                # off again. This is necessary because the tag lets the length
                # of loopvars differ to the length of each set of items and we
                # don't want to leave any vars from the previous loop on the
                # context.
                context.pop()
        context.pop()
        return nodelist.render(context)