在聚合中使用模型方法

时间:2011-09-11 10:47:04

标签: django model aggregate

我正在尝试在django聚合查询中使用模型方法。我不确定是否可能,我可能会以错误的方式去做。

这是我想要查询的模型。

class ClassNumbers(models.Model):
   """
   The class year level and number inline model for a booking
   """
   booking = models.ForeignKey('Booking')
   yearLevel = models.CharField(max_length=10, choices=YEAR_CHOICES, verbose_name='Year Level')
   numberOfStudents = models.IntegerField(verbose_name='Number of Students') 

class Booking(models.Model):
   # A shorter version of the model
   date = models.DateField()
   institution = models.ForeignKey(Institution)

   def getStudentTotal(self):
      # Total class numbers
      classes = ClassNumbers.objects.filter(booking=self.id)
      classTotal = 0
      if ( classes ):
          for c in classes:
              classTotal += c.numberOfStudents
      return classTotal

   def getHDSV(self):
      HDSVunits = {
                'Full-Day': 2.0,
                'Half-Day AM': 1.0,
                'Half-Day PM': 1.0,
                'Three-Quarter Day': 1.5,
                '1 Hour': 0.5,
                'Custom': 1.0,
                }
      numStudents = self.getStudentTotal()
      result = numStudents * HDSVunits[self.price.name]
      return result

getHDSV方法返回应用程序所在内部使用的报告指标。我希望将指标汇总为日期之间的月份总数。

我不是aggregate / annotate主人。到目前为止,我的尝试并未取得我所追求的结果。

最终,我在指定日期之间查询Bookings,然后循环结果,并通过每次迭代调用getHDSV方法将报告单位计入字典。当然,生成的字典没有按照我想要的方式排序。 所以我现在转而寻求帮助。

考虑到生成度量标准的方式,我可以在查询中聚合数据时调用模型方法吗?或者我应该在创建HDSVunits时使用aggregate字典?或者有更好的方法吗?

感谢。

2 个答案:

答案 0 :(得分:2)

您的设置非常困难,可能更容易在HDSVunits模型上使用Price映射,以便在查询中更轻松地进行访问。

我能想到的最好的是:

Booking.objects.aggregate(
    hdsv=(
        Sum('classnumbers__numberofstudents') * 
        Case(
            When(price__name='Full-Day', then=2.0),
            When(price__name='Half-Day AM', then=1.0),
            When(price__name='Full-Day PM', then=1.0),
            When(price__name='Three-Quarter Day', then=1.5),
            When(price__name='1 Hour', then=0.5),
            When(price__name='Custom', then=1.0),
            output_field=FloatField(),
        )
    )
)

如果HDSV值存储为Price模型上的字段,您可以执行以下操作:

Booking.objects.aggregate(
    hdsv=Sum('classnumbers__numberofstudents') * F('price__hdsv'))

另外,您应该考虑遵循Python naming convensions,这将使其他Python开发人员更容易为您提供帮助。

答案 1 :(得分:0)

如果getHDSV返回的数据不是来自数据库,那么aggregateannotate将无法用于收集统计数据。