2

我的 Django 应用程序有一个用户模型,这些用户有很多事务。我的一些观点显示了所有交易金额的汇总(总和),我们称之为“总计”。到目前为止,这已经在需要显示时进行了统计。

现在,我想将这个计数添加到用户查看的每个页面......所以我更希望它来自数据库/模型字段,每个新事务都会维护它。我知道如何做到这一点:在我的用户模型中添加一个“总计”字段,根据需要更新它(使用 Django ORM F()-expressions for race-proof-ness)。到目前为止,一切都很好。

我的问题是关于设置初始“总”值,跟踪到目前为止的所有交易(在运行统计实施之前)。

我想我可以在没有新事务到达的维护窗口期间进行数据迁移,将所有 User.total 值初始化为当前计数。但是,我宁愿不这样做:我所做的最后一次类似的大数据迁移花费的时间比预期的要长。

是否有推荐的技术/技巧可以在没有长时间中断的情况下进行追赶统计,同时新交易也即将到来?

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

4

1 回答 1

2

对于您描述的问题,恐怕没有“一刀切”的解决方案。

在我看来,您对应该做什么很了解,所以让我提出另一种可能的解决方案。

假设您有大量用户并且每个用户都有少量或中等数量的事务(这样处理单个用户的事务不会花费很长时间),您可以在 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()

然后您可以将以下方法添加到您的用户模型中:

@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

于 2014-05-18T12:24:41.920 回答