开发者

Django template: get total iteration count for nested loops

I have two nested for loops inside a template. I need to get the total iterations made since the parent for loop started. The counter needs to be incremented only when the child for iterates.

For example:

Each loop goes from 1 to 3 (included)

Parent loop - 1st iteration

Child loop - 3rd iteration

Wanted result: 3

Parent loop - 2nd iteration

Child loop - 1st iteration

Wanted re开发者_C百科sult: 4

Is there any way I can do this using the standard Django template tags? If not, what are my options?


Write a count template tag which will accumulate in a context variable.

{% for ... %}
  {% for ... %}
    {% count totalloops %}
  {% endfor %}
{% endfor %}
{{ totalloops }}


Either you can use {{forloop.counter |add: forloop.parentcounter.counter }} but depend on the situation if you want to reset the counter then you need to write your own custom python method and later you can call it from django template.

Like in your views add-

class make_incrementor(object):
    count = 0

    def __init__(self, start):
        self.count = start

    def inc(self, jump=1):
        self.count += jump
        return self.count

    def res(self):
        self.count = 0
        return self.count

def EditSchemeDefinition(request, scheme_id):

    iterator_subtopic = make_incrementor(0)
    scheme_recs = scheme.objects.get(id=scheme_id)
    view_val = {
        'iterator_subtopic': iterator_subtopic,
        "scheme_recs": scheme_recs,
    }
    return render(request, "edit.html", view_val)

Later in your django template we can call "iterator_subtopic" methods to increment or reset its value like:-

<td id="subTopic" class="subTopic">
<p hidden value="{{ iterator_subtopic.res }}"></p>
{% for strand in  scheme_recs.stand_ids.all %}
    {{ iterator_subtopic.res }}
    {% for sub_strand in  strand.sub_strand_ids.all %}
        {% for topic in  sub_strand.topic_ids.all %}
            {% for subtopic in  topic.sub_topic_ids.all %}
                <input id="subTopic{{ iterator_subtopic.inc  }}" class="len"
                       value="{{ subtopic.name }}">
                <br>
            {% endfor %}
        {% endfor %}
    {% endfor %}
{% endfor %}

So It will keep incrementing the value and also we can reset it where we want.


With class-based views (specifically using Python 3 and Django 2.1), and using @Javed's answer as a starting point, in the view you can do:

class Accumulator:

    def __init__(self, start=0):
        self.reset(start)

    def increment(self, step=1):
        step = 1 if not isinstance(step, int) else step
        self.count += step
        return self.count

    def reset(self, start=0):
        start = 0 if not isinstance(start, int) else start
        self.count = start
        return self.count

class MyView(ParentView):

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['counter'] = Accumulator()  # use start=-1 for a zero-based index.
        return context

then in the template, you can do:

{% with counter.increment as count %}
  <input id="form-input-{{ count }}">
{% endwith %}


Do you know, going in, how many loops there will be?

If so, an easy way is:

{{ forloop.counter |add: forloop.parentcounter.counter }} etc.

It's a bit stinky vis a vis logic separation (@Ignacio's suggestion is better on this front for sure), but I think it's acceptable if it's kept neat and orderly.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜