Hi all,
Would appreciate some advice on this, I'm having trouble working out the best way to aggregate across multiple foreign key relationships. I have come up with the solution below however I'm not sure if this is the correct way to handle this situation. Any advice would be appreciated.
Thanks
As an example I have a model structure that is 5 levels deep with foreign keys between each level, cost information is recorded at the lowest level (ContractItem)
--- Project
|--- Budget
|--- SubBudget
|--- Contract
|--- ContractItem - $100
If I want to aggregate the total cost up to the top project level I do it in multiple steps like this:
class Project(models.Model):
name = models.CharField(max_length=50)
def total(self):
subbudgets = SubBudget.objects.filter(budget__in=self.budget_set.all())
contracts = Contract.objects.filter(subbudget__in=subbudgets)
return ContractItem.objects.filter(contract__in=contracts).aggregate(Sum('total'))['total__sum']
Is there a better way of doing this?
Full working code:
class Project(models.Model):
name = models.CharField(max_length=50)
def total(self):
subbudgets = SubBudget.objects.filter(budget__in=self.budget_set.all())
contracts = Contract.objects.filter(subbudget__in=subbudgets)
return ContractItem.objects.filter(contract__in=contracts).aggregate(Sum('total'))['total__sum']
def __str__(self):
return
self.nameclass Budget(models.Model):
project = models.ForeignKey(Project)
name = models.CharField(max_length=50)
def __str__(self):
return
self.name def total(self):
contracts = Contract.objects.filter(subbudget__in=self.subbudget_set.all())
return ContractItem.objects.filter(contract__in=contracts).aggregate(Sum('total'))['total__sum']
class SubBudget(models.Model):
budget = models.ForeignKey(Budget)
name = models.CharField(max_length=50)
def __str__(self):
return
self.name def total(self):
return ContractItem.objects.filter(contract__in=self.contract_set.all()).aggregate(Sum('total'))['total__sum']
class Contract(models.Model):
subbudget = models.ForeignKey(SubBudget)
name = models.CharField(max_length=50)
def __str__(self):
return
self.name def total(self):
return self.contractitem_set.aggregate(Sum('total'))['total__sum']
class ContractItem(models.Model):
contract = models.ForeignKey(Contract)
total = models.DecimalField(default=0.00, decimal_places=2, max_digits=12)
name = models.CharField(max_length=50)
def __str__(self):
return
self.name