我的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
检查