Reputation: 4432
I have several models that are related hierarchically:
Simplified Models:
class Project(models.Model):
id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
name = models.CharField(max_length=255)
class Experiment(models.Model):
id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
name = models.CharField(max_length=255, blank=False)
project = models.ForeignKey('Project', related_name='experiments', on_delete=models.CASCADE)
class Scan(models.Model):
id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
name = models.CharField(max_length=127, blank=False)
experiment = models.ForeignKey('Experiment', related_name='scans', on_delete=models.CASCADE)
class ScanDecision(models.Model):
id = models.UUIDField(primary_key=true, default=uuid4, editable=False)
scan = models.ForeignKey('Scan', related_name='decisions', on_delete=models.CASCADE)
If I have a specific Scan Decision and I want to get the Project associated with that decision, how can I do so?
The Django documentation speaks of backward relationships but the examples seem limited to a single level of relationship.
For example, to get the ScanDecision
associated with a Scan
I could do something like:
sd = ScanDecision.objects.get(id=1)
sd.scan_set.all() # Returns all scan objects related to the specific ScanDecision
But what if I want to get the Project
that is associated with the ScanDecision
indirectly through Scan
and Experiment
?
e.g., something like this but without all the steps?
sd = ScanDecision.objects.get(id=1) # The desired ScanDecision object
s = sd.scan_set.all() # Gets the related Scan object
e = s.experiment_set.all() # Gets the Experiment related to the selected Scan object
p = e.project_set.all() # Gets the Project related to the selected Experiment object
Ideally I'd like something like:
sd = ScanDecision.objects.get(id=1)
p = sd.project_set.all()
Note: Each object only knows about it's immediately antecedent object, e.g. there is an ForeignKey relationship setup only between the child and parent objects, not any other levels. Thus ScanDecision
has an FK to Scan
but not to Experiment
or Project
. Similarly, Scan
has an FK to Experiment
but not to Project
.
Upvotes: 0
Views: 204
Reputation: 1029
Based on your update you can use forward relationship sd.scan.experiment.project
. To answer the question though to access backward relationship you could do decisions = project.experiments.scans.decisions.all()
Upvotes: 1