将 Django/South/PostgreSQL 从按需计算的摘要值迁移到数据库中维护的摘要值的正确方法是什么?



我的Django应用程序有一个用户模型,这些用户有许多事务。我的一些视图显示了所有交易金额的汇总(总和),我们称之为"total"。到目前为止,这些数据都是在需要显示时统计出来的。

现在,我想将这个计数添加到用户视图的每个页面…所以我更希望它来自每个新事务维护的DB/model字段。我知道如何做到这一点:在我的User模型中添加一个'total'字段,根据需要更新它(使用Django ORM F()-表达式进行种族证明)。到目前为止一切顺利。

我的问题是关于设置初始的"total"值,跟踪到目前为止的所有事务(在运行计数实现之前)。

我想我可以,在没有新的事务到达的维护窗口,做一个数据迁移初始化所有的User。当前计数的总价值。然而,我宁愿不这样做:我做的上一次类似的大数据迁移花了比预期多几个小时的时间。

在新事务也到达的情况下,有没有推荐的技术/技巧可以在不长时间中断的情况下进行追赶计数?

我想我可以编写追赶数据迁移,以便在部署新的计数维护代码时只考虑阈值日期(或id)之前的事务。(然后,我将在系统启动时运行数据迁移,并且只在迁移完成时在界面中显示新的计数,而不管这需要多长时间。)但是,我宁愿不将这个日期/id阈值编码到迁移源代码中。南方是否存在可用于此目的的元数据?

对于你所描述的问题,恐怕没有"一刀切"的解决办法。

在我看来,你似乎很清楚应该做什么,所以让我建议另一个可能的解决方案。

假设你有大量的用户,每个用户都有少量或中等数量的事务(这样处理单个用户的事务就不会花费很长时间),你可以在你的South数据迁移中做这样的事情(使用旧的Django事务,因为你在Django 1.6发布之前问过这个问题):

from django.db import transaction
for user in orm.User.objects.all():
    with transaction.commit_on_success():
        user._total = calculate_sum_of_transactions_for_user(user)
        user.transactions_migrated = True
        user.save()
然后,您可以将以下方法添加到您的User模型中:
@property
def total(self):
    if self.transactions_migrated:
        return self._total
    else:
        return calculate_sum_of_transactions_for_user(user)

事务创建代码可以像这样:

class Transaction(models.Model):
    amount = models.DecimalField(...)
    def save(self, ...):
        super().save(...)
        if self.user.transactions_migrated:
            self.user._total = F('_total') + self.amount
            self.user.save()

您甚至可以去掉transactions_migrated字段并将其替换为一些_total is None检查

相关内容

  • 没有找到相关文章

最新更新