在Django模型的属性中使用聚合

时间:2011-10-19 19:53:21

标签: django django-models django-aggregation

架构描述

enter image description here

项目可能有多个项目项目,项目项目可能有多个购置成本。例如,资本项目#1包含两个项目项目:

  1. 数量。购买1台生产设备
    • 从供应商处购买设备需要花费5,000美元
  2. 数量。由工作人员构建的1个测试夹具
    • 每次购买12,000美元,总购买成本为12,000美元。
  3. 生产设备可能只有一个与购买相关的成本。但是,测试夹具可能会产生与构建它相关的多个成本。

    欲望

    我希望能够确定每个项目的总购置成本,并且我希望能够确定每个项目的总购置成本。基于上面的例子:

    • 第1项总购置成本= $ 5,000
    • 第2项总购置成本= 12,000美元
    • 资本项目总购置成本= 17,000美元

    问题

    1. total_acquisition_costs是应该使用Django的聚合计算还是DecimalFieldProject模型上保存为ProjectItem
    2. 我应该为total_acquisition_costsProjectItem模型创建Project属性吗?创造财产我的直觉是肯定的。

      我的直觉是使用聚合来计算值,以避免数据库非规范化。具体来说,我倾向于使用Django的聚合Sum函数来创建total_acquisition_costs属性。但是,我并不知道如何将聚合作为属性放在模型上,以便它只返回一个值而不是一个字典。

    3. 当前代码

      注意:我当前的代码不使用Django的聚合功能,但它可以正常工作。

      class ProjectItem(models.Model):
          project = models.ForeignKey(CapExProject)
          name = models.CharField(max_length=128)
      
          @property
          def total_acquisition_costs(self):
              acquisition_costs = self.acquisitioncost_set.only(
                      'amount')
              total_acquisition_costs = 0
              for acquisition_cost in acquisition_costs:
              total_acquisition_costs += acquisition_cost.amount
              return total_acquisition_costs
      

1 个答案:

答案 0 :(得分:13)

我喜欢你使用Sum的想法,但是把它变成了属性。这样的事情应该有效:

class Project(models.Model):
    @property
    def total_acquisition_costs(self):
        return AcquisitionCost.objects.filter(item__project=self).aggregate(total=Sum("amount"))["total"]

class ProjectItem(models.Model):
    @property
    def total_acquisition_costs(self):
        return self.acquisitioncost_set.aggregate(total=Sum("amount"))["total"]