假设我们有一个包含以下字段的钱包表:id,user_id,total,frozen,active,update_time。
每个用户在此表中只有一条记录,并且将一直更新。
例如
{
id: 1,
user_id: 100,
total: 50.5,
freeze: 0,
active: 50.5,
update_time: 2018-07-17 16:43:41,
}
当用户获得5美元时,我该如何使用 update_or_create()方法来更新总字段,冻结字段和活动字段取决于它们的原始值?
income = 5.0
Wallet.objects.update_or_create(
user_id=obj.user.id,
defaults={
'update_time': datetime.now(),
'active': F('active') + income,
'total': F('total') + income,
}
)
我尝试了F(),效果很好!
{
id: 1,
user_id: 100,
total: 55.5,
freeze: 0,
active: 55.5,
update_time: 2018-08-26 07:12:15,
}
但是,如果用户在钱包表中没有记录,这意味着这是他/她第一次赚钱,那么出问题了:
Failed to insert expression "Col(wallet, Wallet.total) + Value(5.0)" on Wallet.total. F() expressions can only be used to update, not to insert.
如果我真的想使用 update_or_create(),该如何解决?
需要您的帮助,谢谢!
答案 0 :(得分:2)
您不能根据需要使用 F()
功能。您可以做的是,检查对象是否存在并执行操作。
income = 5.0
if Wallet.objects.filter(user_id=obj.user.id).exists():
Wallet.objects.update_or_create(
user_id=obj.user.id,
defaults={
'update_time': datetime.now(),
'active': F('active') + income,
'total': F('total') + income,
}
)
else:
Wallet.objects.create(user_id=obj.user.id, **{'update_time': datetime.now(),
'active': income,
'total': income,
})
答案 1 :(得分:-1)
@JPG提出的解决方案受竞争条件的影响。根据使用情况,您可以尝试如下操作:
obj, created = ProductRedirectStats.objects.get_or_create(
date=date.today(), product_id=product_id, defaults={"redirects": 1}
)
if not created:
ProductRedirectStats.objects.filter(date=date.today(), product_id=product_id).update(redirects=F("redirects") + 1)