Reputation: 1990
I have two models:
class User(models.Model):
# stuff
class Task(models.Model):
# stuff
When assigning new tasks to users, I want to avoid assigning tasks the worker has gotten before. The approach I'm trying to take is to add a third model, Assignment
that tracks tasks assigned to a given user:
class Assignment(models.Model):
worker = models.ForeignKey(User)
task = models.ForeignKey(Task)
How, though, do I go about forming a query based on this? My thought was to start by filtering Assignments by the user being assigned to, but I'm getting stuck after that point.
def get_tasks(worker):
previous_assignments = Assignment.objects.filter(worker=worker)
# then something like...
assignable_tasks = Task.objects.exclude(pk__in=previous_assignments.task) #clearly wrong
Is there a way to access the task ids inside the previous_assignments
queryset? Not sure if this isn't the best approach, or if I am just missing how to move past this step.
Edit: It occurs to me I could populate an empty set with Task
s by looping through those Assignment
objects and then use an __in
exclude argument like above... Any better approaches than that?
Upvotes: 1
Views: 1672
Reputation: 308839
In order to exclude with pk_in
, you would need a list or queryset of task ids to exclude. For example you could do:
previous_assignments = Assignment.objects.filter(worker=worker).values_list('task_id')
assignable_tasks = Task.objects.exclude(pk__in=previous_assignments)
However you don't need to do this. You can use the double underscore notation to follow the relationship from assignment to worker:
assignable_tasks = Task.objects.exclude(assignment__worker=worker)
Note that you could use a many-to-many field instead, and Django will take care of creating the joining table for you:
class Task(models.Model):
users = models.ManyToManyField(User)
In this case, your query becomes:
assignable_tasks = Task.objects.exclude(users=worker)
Upvotes: 1