将django模型管理器的结果保存到数据库

时间:2011-11-15 18:47:45

标签: django

我想提供关于班级实例的一般统计数据" ModelClass"在我的用户的网页上。可以说有几千个ModelClass对象,我需要计算很多统计数据。我已经发现我可以用模型管理器做到这一点,这是一个(非常)简化的例子:

class ModelClassCustomManager(models.Manager):
    def get_query_set(self):
        return super(ModelClassCustomManager, self).get_query_set().filter(is_complete = True)


class ModelClass(models.Model):
    is_complete = models.BooleanField(default = False)
    ...
    objects = models.Manager()
    complete_objects = ModelClassCustomManager()

我担心的是,如果用户查看页面时会计算出大量资源。因此,我想在我更改或创建新的ModelClass对象时计算它,因为这是统计数据真正改变的唯一时间。我想这可以通过重写ModelClass save() - 方法来完成。

保存这些结果的最佳方法是什么?我应该创建另一个用于保存计算统计数据的django模型,还是存在另一种存储此信息的方法?

编辑:感谢pastylegs得到了一个很好的答案。这样做会产生一些小错误,我想我会在这里解释它们,以防其他人遇到这个问题。

首先,我错误地将ModelClass中的导入放在顶部,因此我得到了循环依赖,这给出了一些奇怪的结果。为了节省一些挫折感,把它们放在pastylegs的位置。其次,为了覆盖以前的统计计算(而不是每次都创建一个新计算),只需替换

if sender is ModelClass and instance is not Null:
    count = ModelClass.objects.all().count()
    stat = Stat(name='some_name', value=count).save()

用这个:

if sender is ModelClass:
    count = Match.objects.all().count()
    try:
        stat = Stat.objects.get(key="Total")
        stat.update(key="Total", value=count) #Update statistic
    except: 
        Stat(key="Total", value=count).save() #Create new

1 个答案:

答案 0 :(得分:4)

我创建了一个名为statistics(或类似)的应用程序,它有一个简单的模型来保存键值对:

class Stat(models.Model):
    key = models.CharField(..)
    value = models.CharField(...)

然后在每次用户保存/更新模型实例时,在您自己的模型上使用信号来运行函数。在 models.py

class ModelClass(models.Model):
    ...

from django.db.models.signals import post_save
from myapp.signal import updates_stats
post_save.connect(updates_stats, sender=ModelClass)

然后创建接收器函数以计算 signals.py

中需要的统计信息
from myapp.models import ModelClass
from stats.models import Stat
def update_stats(sender, instance, signal, *args, **kwargs):
    if sender is ModelClass and instance is not Null:
        count = ModelClass.objects.all().count()
        stat = Stat(name='some_name', value=count).save()

这是一种非常简单和基本的方法,仅概述了如何利用信号进行计算,但这是一个良好的开端。理想情况下,您应该尝试在请求/响应周期之外计算这些值(特别是如果它们是大的计算),因为它会挂起您的服务器并可能超时您的请求,因此您应该考虑使用像Celery这样的排队/任务系统来执行在后台计算