Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

209
Views
Django filtering relation in ListView

Given the models

class TaskGroup(models.Model):
    name = models.CharField(max_length=256)

class Task(models.Model):
    name = models.CharField(max_length=256)
    group = models.ForeignKey(TaskGroup, on_delete=models.CASCADE)
    completed = models.BooleanField(default=False)
    completed_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)

and the list view

class TaskGroupListView(ListView):
   model = TaskGroup

I'd like to display the list of task groups with corresponding tasks. The catch is - I only want to show the tasks that have not been completed or have been completed by the user, or if the user as the attribute user.type == "ADMIN" set show all groups and all tasks.

Right now I have a template that looks like:

{% for taskgroup in object_list %}
<h1>{{ taskgroup.name }}</h1>
<ul>
    {% for task in taskgroup.task_set.all %}
    <li>{{ task.name }}</li>
    {% endfor %}
</ul>
{% endfor %}

I know that I can modify the queryset of a list view by overriding get_queryset like:

def get_queryset(self):
    if self.request.user == "ADMIN":
        return TaskGroup.objects.all()
    else:
        ...

but I'm not sure how to go about filtering the Task relations on the TaskGroups in the else clause.

I've thought about creating a manager subclass for Task that can filter based on .completed and .completed_by that I can use in the template but that seems against the philosophy of Django - I'd like to keep all the logic in the view (this may be way off the mark so please correct me, its been a while since I've touched django/read two scoops of django).

Is there some idiomatic way to do this? Should I discard ListView entirely and write some custom logic? any guidance here is helpful. Thanks.

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

You can use prefetch_related with a Prefetch that uses a custom filtered queryset like this:

from django.db.models import Prefetch, Q


def get_queryset(self):
    if self.request.user.is_admin:
        return TaskGroup.objects.all()

    return TaskGroup.objects.prefetch_related(
        Prefetch(
            'task_set',
            queryset=Task.objects.filter(Q(completed=False) | Q(completed_by=self.request.user))
        )
    )

This will get all the TaskGroups with the related Taskss (in task_set) filtered by those that are not yet completed or are completed by the current user.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!