0

I have two models : WorkflowStep and WorkflowStepPR. (PR stands for prerequisite).

class WorkflowStep(BaseModel):
    name = models.CharField(max_length=200)
    workflow = models.ForeignKey('Workflow', on_delete=models.CASCADE)
    allowed_status = models.ManyToManyField('WorkflowStepStatus', related_name='workflow_step')
    default_status = models.ForeignKey('WorkflowStepStatus', blank=True, null=True, on_delete=models.SET_NULL)
    recheck_on_new_version = models.BooleanField(default=False)
    watch_folder = models.BooleanField(default=False)

    def __str__(self):
        return self.name

    class Meta:
        ordering = ['created_on'] 

class WorkflowStepPR(BaseModel):
    PR_for = models.ForeignKey('WorkflowStep', related_name='PR_for', on_delete=models.CASCADE)
    PR_step = models.ForeignKey('WorkflowStep', related_name='as_PR_step', on_delete=models.CASCADE)
    PR_step_status = models.ForeignKey('WorkflowStepStatus', on_delete=models.CASCADE)

    def __str__(self):
        return "{} 's PR - {}".format(self.PR_for, self.PR_for.workflow)

    class Meta:
        ordering = ['created_on']

Every WorkflowStep has a prerequisite which is maintained via WorkflowStepPR model. Now assume that I have the below scenario:

enter image description here

Every box represents a workflow step. Every arrow connecting two boxes shows pre requisite relation (i.e. box on the right of the arrow is dependent on the box on the left of the arrow). For example : "B" is the pre requisite for "C" and "D".

I want to find all the steps which are directly or indirectly related to Step B.

Directly related : C, D

Indirectly Related: E (related to C), G (related to C), H(related to D), J (related to H)

How can I write a query the to get this?

I have tried the following

@receiver(pre_save, sender=WorkflowInstanceStep)
def status_of_workflowInstanceStep_updated(sender, instance,**kwargs):
    if instance.id is None:
        pass

    else:
        workflow_step = instance.workflow_step
        dependent_steps = workflow_step.as_PR_step.all()
        print(dependent_steps)

But this returns just the step C and Step D in the queryset.

EdG
  • 2,243
  • 6
  • 48
  • 103
  • Are there any restrictions on the length of the formed tree? – Ersain Jun 30 '22 at 10:13
  • No. There is no restrictions @Ersain – EdG Jun 30 '22 at 10:14
  • What database are you using? You can use recursive CTEs with raw SQL in databases that support it, see [How to recursively query in django efficiently?](https://stackoverflow.com/questions/39511993/how-to-recursively-query-in-django-efficiently). I don't think there is a django-native way to solve this in a single query. You can obviously loop and get the result in N queries. – He3lixxx Aug 28 '23 at 12:18
  • Here is an answer for what you are looking, There a some libraries for operating with trees https://stackoverflow.com/a/76474115/7851254 – Alexandr Zayets Sep 01 '23 at 08:48

0 Answers0