Search code examples
htmldjangotags

Django HTML Tags - Merge For Loop with Conditional Statement


I am using Django and I am wondering if there is a way to modify the tags below so that the for loop stops iterating once a specific condition is met?

webpage.html
<div>
{% for person in crew.crew_set.all %}
   {% if person.job|stringformat:'s' == 'Supervisor'  %}
       <div>Supervisor</div>
   {% endif %}
{% endfor %}
</div>

The code above results in "Supervisor" being written 50 times. Can I merge the two tags or use a break statement somehow so "Supervisor" is only listed once?

I'm not listing my models / views because I'm really just trying to get a better understanding of how to use tags on my html pages.

Details:

Models.py

class Person(models.Model):
    name = models.CharField(max_length=200)

class Jobs(models.Model):
    jobcode = models.CharField(max_length=5)
    name = models.CharField(max_length=200)

class Crew(models.Model):
    jobnumber = models.ForeignKey(Jobs, on_delete=models.CASCADE)
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    role = models.CharField(max_length=200)

Views.py

class PersonPageView(DetailView):
    model = Person
    queryset = Person.objects.prefetch_related(
        Prefetch('jobs_set', Jobs.objects.select_related('jobnumber')),
        Prefetch('crew_set', Crew.objects.select_related('person'))
    )
    template_name = '_person_info.html'

Solution

  • Please don't do this in the template. Templates should be used to implement rendering logic, not business logic. Templates are not very efficient, but also deliberately lack all sorts of tooling to prevent people from doing this.

    You can use an Exists subquery to check this, this will also boost efficiency:

    from django.db.models import Exists, OuterRef
    
    
    class PersonPageView(DetailView):
        model = Person
        queryset = Person.objects.prefetch_related(
            Prefetch('jobs_set', Jobs.objects.select_related('jobnumber')),
            Prefetch('crew_set', Crew.objects.select_related('person')),
        ).annotate(
            is_supervisor=Exists(
                Crew.objects.filter(person_id=OuterRef('pk'), role='Supervisor')
            )
        )
        template_name = '_person_info.html'

    The person will then have an extra attribute .is_supervisor, so you can use:

    {% if person.is_supervisor %}
        …
    {% endif %}