slechani
slechani

Reputation: 47

Using reverse ForeignKey relation to get count of children for current object not working properly

I'm currently making a Todo app, I have multiple Todolist that can each contain multiple tasks, here's how I made my models :

class Todo(models.Model):
    name = models.CharField(max_length=120)
    total_tasks = models.IntegerField(default=0)
    completed_tasks = models.IntegerField(default=0)

    def update_total_tasks(self):
        self.total_tasks = self.task_set.all()

    def _str_(self):
        return self.name


class Task(models.Model):
    name = models.CharField(max_length=120)
    completed = models.BooleanField(default=False)
    todo = models.ForeignKey(Todo, on_delete=models.CASCADE, related_name="tasks")

My todo contains all current tasks as well as completed tasks, the update_total_tasks function is meant to query all tasks linked to that particular todo and update the field accordingly.

This function is called each time a task is created / updated with :

@receiver(models.signals.post_save, sender=Task)
def execute_after_save(sender, instance, created, *args, **kwargs):
    instance.todo.update_total_tasks()

The receiver works and calls my update function properly though it seems the query is done the wrong way because I get this error :

AttributeError: 'Todo' object has no attribute 'task_set' 

Do you have any idea on why it's not working properly ?

Thanks.

Upvotes: 1

Views: 20

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476584

The related_name=… parameter [Django-doc] is set to 'tasks'. Hence you access the relation in reverse with .tasks.

You thus access this with:

class Todo(models.Model):
    name = models.CharField(max_length=120)
    total_tasks = models.IntegerField(default=0)
    completed_tasks = models.IntegerField(default=0)

    def update_total_tasks(self):
        self.total_tasks = self.tasks.count()

Upvotes: 2

Related Questions