How to filter data from parant model based on if there relationship with child model

I have these models


class Tree(models.Model):
    field = models.TextField()

class TaskProgress(models.Model):
    base_task = models.ForeignKey(BaseTask, on_delete=models.CASCADE)
    tree = models.ForeignKey(Tree, on_delete=models.CASCADE)

class BaseTask(models.Model):
   trees=models.ManyToManyField(Tree, through='TaskProgress')


class TaskType1(BaseTask):
   child1_field = models.TextField()

class TaskType2(BaseTask):
   child2_field = models.TextField()

how to get all taskprogress when related to TaskType2 ,

TaskProgress.objects.filter(???)

I do not think what you are asking is possible, if the models are designed like described. The base_task ForeignKey is specifically pointing at a BaseTask. Even though TaskType1 and TaskType2 inherit from BaseTask, they have no relation in the database. They only look similar.

Option 1: Look into Generic Relations in Django. Basically it allows you to have a ForeignKey relation with more than one type of model. I would not recommend it though. Generic relations are a mess if you don't know want you are doing.

Option 2: Rethink your layout. Maybe you can move the relation to the two TaskTypes instead and adress them via related_name.

class TaskProgress(models.Model):
    # base_task = models.ForeignKey(BaseTask, on_delete=models.CASCADE)
    tree = models.ForeignKey(Tree, on_delete=models.CASCADE)

class TaskType1(BaseTask):
   task_progress = models.OneToOneField(TaskProgress, related_name='task_type_1'
   child1_field = models.TextField()

class TaskType2(BaseTask):
   task_progress = models.OneToOneField(TaskProgress, related_name='task_type_2'
   child2_field = models.TextField()

This way you create a one-to-one-relation between the TaskProgress and the TaskType. You should be able to query one or the other by checking whether a relation exists, e.g. all TaskProgress instances with a relation to a TaskType1 instance.

# Query all TaskProgress instances, that have a TaskType1
TaskProgress.objects.filter(task_type_1__isnull=False)

I added extra field on BaseTask class

TASK_TYPE =[('I','Irrigation'),('C','Care'),('A','Assessment'),('O','Other')]

class BaseTask(models.Model):
    trees=models.ManyToManyField(Tree, through='TaskProgress')
    worker = models.ManyToManyField(User)
    task_type = models.CharField(max_length=1,choices=TASK_TYPE,null=True)

And the filter will be like this

TaskProgress.objects.filter(base_task__task = "I")
Back to Top