如何使用Django Queryset update()函数与F()引用的外键字段?



我想做一个简单的查询:

with transaction.atomic():
Account.objects.select_for_update().filter(payments__status='PENDING', payments__created_date__lt=timezone.now()-timedelta(days=14)).update(balance=F('balance')+Sum(F('payments__amount') - F('payments__payment_fee__fee_amount')), payments__status='COMPLETED')

结果一点也不简单。我已经尝试了子查询,但是在此查询中不允许获得"连接字段引用"。

不允许使用GROUP BY子句">

子查询不能工作,因为聚合不能与select_for_update()锁一起工作。F()不能工作,因为它引用了外键字段…

使这个查询工作的最好方法是什么?任何想法?

  • 我在ORM后面使用postgresql。

我是这样做的:

with transaction.atomic():
payments_due_payout = models.Payment.objects.filter(status='PENDING', created_date__lt=timezone.now()-timedelta(days=15))
total_payout = Subquery(models.Account.objects.filter(payments__in=payments_due_payout, id=OuterRef('id')).annotate(total_payout=Sum(F('payments__amount') - F('payments__payment_fee__fee_amount'))).values('total_payout')[:1])
models.Account.objects.select_for_update().filter(payments__in=payments_due_payout).update(balance=F('balance')+total_payout)
payments_due_payout.update(status='COMPLETED')

在update()函数中用F引用外键字段可以用Subquery解决。但是你不能聚合被select_for_update()锁定的行。

我选择依靠"payments_due_payout"这是不可能从客户端修改timezone.now()-timedelta(days=14),我获取支付create_date_lt =timezone.now()-timedelta(days=15),这是一天的差异。我不认为任何对payments_due_payments的并发请求会在Django服务器上持续一天。

所以应该没有问题,但是在理想情况下,我们应该完全防止通过编程方式更改status='PENDING'的数据的可能性。

如果你有更好的主意,请告诉我。

相关内容

  • 没有找到相关文章

最新更新