Search code examples
djangodjango-templatesdjango-template-filters

Count booleans inside a for-loop in a django template


I would like to know how to count all the true/false booleans inside a for-loop in my django template, but im not sure how to achieve this inside the loop. My goal is to show the user how many questions are unsolved/solved.

lets say these are my models:

class Category(models.Model):
    name = models.CharField(max_length=50)

class Question(models.Model):
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    title = models.CharField(max_length=50)
    description = models.TextField(max_length=250)
    solved = models.BooleanField(default=False)

ListView:

class CategoryView(ListView):
    model = Category
    context_object_name = 'categories'

Template:

{% for category in categories %} 
    {{ category.name }}         # I would like to show: 5/10 questions solved
    {% for question in category.question_set.all %} 
        {{ question.name }}
        {{ question.title }}
        {{ question.description }}
        {{ question.solved }}
    {% endfor %}
{% endfor %}

Usually i print the total number of objects with .count like: {{ cagetories.count }}
But i cant do this inside the loop because it returns: 1 1 1 1 1 1:

{% for question in category.question_set.all %}
    {% if not question.solved %}
        {{ question.count }} ## returns 1 1 1 1 1 1
    {% endif %}
{% endfor %}

Same thing with the {{ forloop.counter }} it returns multiple numbers because of the loop, but i only need that last number:

{% for question in category.question_set.all %} 
    {% if not question.solved %}
        {{ forloop.counter }} # returns; 1 2 3 4 5 6
    {% endif %}
{% endfor %}

my question; Is this possible inside the template or do i need another approach?


Solution

  • It would be better practice to compute this inside the view than in the template:

    class CategoryView(ListView):
        model = Category
    
        def get(self, request, *args, **kwargs):
            categories = []
            for category in self.get_queryset():
                questions = category.question_set.all()
                count = sum([q.solved for q in questions])
                categories.append([questions, count])
            return render(request, 'TEMPLATE NAME HERE', {'categories': categories})
    

    Now in the template you can loop through each category and also have access to the solved count:

    {% for questions, solved_count in categories %} 
        {# display solved count and then loop through questions #}
    {% endfor %}