0

How to reset the forloop counter in django template?

This is my current QuerySets:

context['major'] = Major.objects.all().filter(is_active=True).order_by('id')
context['minor'] = Minor.objects.all().filter(is_active=True).order_by('id')

And this is my Models:

class Major(models.Model):
    major_name = models.CharField(max_length=100, default='', null=False)
    is_active = models.BooleanField(default=True, null=False)
    
    def __str__(self):
        return self.major_name

class Minor(models.Model):
    major_name = models.ForeignKey(Major, on_delete=models.CASCADE)
    minor_name = models.CharField(max_length=100, default='', null=False)
    is_active = models.BooleanField(default=True, null=False)
    
    def __str__(self):
        return self.minor_name

So I have something like this:

{% for major in majors %}
    {% for minor in minors %}
        {% if minor.major_name == major %}
            {{forloop.counter}} {{minor}}
        {% endif %}
    {% endfor %}
{% endfor %}

Current output:

major1
    1 minor1
    2 minor2
major2
    3 minor3
    4 minor4
    5 minor5
    ...

I want it to display something like:

major1
    1 minor1
    2 minor2
major2
    1 minor3
    2 minor4
    3 minor5
    ...
5
  • Can you add the majors and minors models and querysets to your question? It may be easier to change the way you define or iterate over your data as "resetting" the forloop counter like you ask is not trivial/possible Commented Feb 20, 2021 at 4:03
  • Added my querysets. Commented Feb 20, 2021 at 4:06
  • I also tried adding the {%with%} tag inside template but I dont think I can increment the variable from with tag Commented Feb 20, 2021 at 4:07
  • Can you add the models too? Commented Feb 20, 2021 at 4:08
  • Added it too... Commented Feb 20, 2021 at 4:14

1 Answer 1

1

It seems like what you are trying to achieve is displaying all Minor instances related to a Major instance filtered and indexed.

Rather than looping over all filtered Minor instances again and again, you can pass a Prefetch object to prefetch_related to add a filter to the related queryset (major.minor_set) for the reverse relationship and then loop over that

context['majors'] = Major.objects.filter(
    is_active=True
).prefetch_related(
    Prefetch('minor_set', queryset=Minor.objects.filter(is_active=True).order_by('id'))
).order_by('id')

Then in the template

{% for major in majors %}
    {% for minor in major.minor_set.all %}
        {{ forloop.counter }} {{ minor }}
    {% endif %}
{% endfor %}
Sign up to request clarification or add additional context in comments.

13 Comments

Thank you for the response. I got an error minor_set' is an invalid parameter to prefetch_related() after implementing.
and django is pointing to for major in majors.
Is the Minor -> Major foreign key exactly as described in your question? It does not have a related_name so the reverse relation must be named minor_set?
Minor -> Major ForeignKey yes. But no related name.
Running a test locally using your models works fine for me. What is the full error message? Does it start with Cannot find 'minor_set' on Major object?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.