我一直在使用Django F()对象来更新我的模型,以避免竞争条件。
我的模型也有自定义保存方法(我希望反叛者的范围从0到100)。
以下是一些示例代码:
class World(models.Model):
...
world.rebels = models.IntegerField(default=0)
...
def save(self, *args, **kwargs):
...
if self.rebels > 100:
self.rebels = 100
elif self.rebels < 0:
self.rebels = 0
...
super(World, self).save(*args, **kwargs)
现在我有一个功能可以为反叛计数添加数量。
world = World.objects.get(worldid=1)
rebchange = 0
print world.rebels
>>> 0
world.rebels = F('rebels') + rebchange
print world.rebels
>>> (+: (DEFAULT: ), 0)
world.save()
print world.rebels
>>> 100
多奇怪吧?增量完全是错误的值!然后,我使用涉及self.rebels的条件注释掉了自定义保存方法,然后模型将正确的值保存到数据库中。
显然,(+: (DEFAULT: ), 0) > 100
不知何故True
,并触发更改为100。
我已将自定义保存方法更改为:
def save(self, fsave=False, *args, **kwargs):
if fsave == False:
...
if self.rebels > 100:
self.rebels = 100
elif self.rebels < 0:
self.rebels = 0
...
super(World, self).save(*args, **kwargs)
在我的函数中,然后我调用world.save()两次:
world = World.objects.get(worldid=1)
rebchange = 0
world.rebels = F('rebels') + rebchange
world.save(fsave=True)
world.save()
print world.rebels
>>> 0
为了能够在保存F()对象时避免我的自定义保存,然后使用正确的值强制执行自定义保存。
这是预期的行为,如果是这样,是否有更简单的方法来完成我想要做的事情?
答案 0 :(得分:2)
在比较Python中的不同类型时,数字总是在其他对象之前排序。因此,100
总是低于F()
对象。
你确实需要进行特殊情况测试;您可以改为测试self.rebels
是F
的实例:
def save(self, *args, **kwargs):
...
if not isinstance(self.rebels, F):
if self.rebels > 100:
self.rebels = 100
elif self.rebels < 0:
self.rebels = 0
...
super(World, self).save(*args, **kwargs)
Python 2支持排序混合类型列表,同时保证稳定的排序顺序。
因为这种行为可能导致细微的意外错误(与您的情况完全相同),所以Python 3中已删除此行为,并且仅支持明确支持比较的类型。