Django的。在数据库中进行复杂计算

时间:2012-10-12 04:02:19

标签: python django django-models

这是我的模型文件的一部分:

class Metric(models.Model):
    Team = models.ForeignKey(Team)
    metric_name = models.CharField(max_length = 40)
    def __unicode__(self):
            return self.metric_name


class Members(models.Model):
    Metric = models.ForeignKey(Metric, through="Calculate")
    member_name = models.CharField(max_length = 40, null=True, blank=True)
    week_one = models.IntegerField(null=True, blank=True)
    week_two = models.IntegerField(null=True, blank=True)
    week_three = models.IntegerField(null=True, blank=True)
    week_four = models.IntegerField(null=True, blank=True)
    total = models.IntegerField(null=True, blank=True)
    def __unicode__(self):
            return self.member_ID

    def save(self, *args, **kwargs):
            self.total = int(self.week_one)+int(self.week_two)+int(self.week_three)+int(self.week_four)
            super(Members, self).save(*args, **kwargs) # Call the "real" save() method.

现在我想做的是。我想计算每个指标的成员数量,指标中所有成员的总计,以及指标中所有成员的最高总数。

我无法想办法在Django中做到这一点。 我想进行这些计算并将它们存储在数据库中。 任何人都可以帮我解决这个问题。 感谢

1 个答案:

答案 0 :(得分:0)

如果您希望“记住”这些结果,至少有两条路径可供您遵循:

  1. 成员表上的每行后保存触发器,用于更新度量标准表中的“members_count”,“members_total”和“members_max”字段。

    这样做的挑战在于将触发器创建DDL与代码的其余部分一起维护,并在重新创建或更改模型时自动应用它。

    Django ORM并不能让这一切变得特别容易。最常见的迁移工具(南方)也不会让它变得容易。另请注意,此解决方案将特定于一个RDBMS,并且某些RDBMS可能不支持此。

  2. 您可以在Metric模型中创建“合成”字段,然后使用保存后信号处理程序在添加或更改成员时更新它们。

    class Metric(models.Model):
        Team = models.ForeignKey(Team)
        metric_name = models.CharField(max_length = 40)
    
        members_count = models.IntegerField()
        members_max = models.IntegerField()
        members_total = models.IntegerField()
    
        def __unicode__(self):
            return self.metric_name
    
    # signal handling
    from django.db.models import signals
    from django.dispatch import dispatcher
    
    def members_post_save(sender, instance, signal, *args, **kwargs):
        # Update the count, max, total fields
        met = sender.Metric # sender is an instance of Members
        metric.members_count = Members.objects.filter(Metric=met).count()
        # more code here to do the average etc;
    
    dispatcher.connect(members_post_save, signal=signals.post_save, sender=Members)
    
  3. django信号文档here可以使用。

    <强>注意事项

    1. 虽然可以采用这种方法来实现您的既定目标,但它很脆弱。您需要具有测试覆盖率,以确保即使在您对代码进行了一些重构之后,此信号处理程序也会始终触发。
    2. 我还会考虑使用“相关对象”查询[记录在https://docs.djangoproject.com/en/dev/topics/db/queries/#related-objects],例如,假设我们有一个“我”的度量标准实例

      >> members_count = me.members_set.count()
      >> # aggregation queries for the total and max
      
    3. 如果不经常使用这些聚合,那么路径#2可能是一个可行且更易于维护的选项。