我有一种情况需要更新候选人的投票。
公民可以为这位候选人投票,每名候选人获得多于一票。即一个人可以投票5票,而另一个人投票2.在这种情况下,这个候选人应该得到7票。
现在,我使用 Django 。这里伪代码看起来像
votes = candidate.votes
vote += citizen.vote
这里的问题,正如你所看到的那样是一个 竞争条件 ,其中候选人的投票可能会被另一个公民的投票覆盖,他们之前选择了一个并立即设置。
如何使用像
答案 0 :(得分:2)
如果这只是一个算术表达式,那么Django有一个很好的API叫F expressions
根据现有字段更新属性
有时您需要在字段上执行简单的算术任务,例如递增或递减当前值。实现这一目标的显而易见的方法是执行以下操作:
>>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
>>> product.number_sold += 1
>>> product.save()
如果从数据库中检索到的旧number_sold值为10,那么值11将被写回数据库。
可以通过相对于原始字段值表示更新来略微优化,而不是作为新值的显式赋值。 Django提供F()表达式作为执行此类相对更新的方式。使用F()表达式,前面的示例将表示为:
>>> from django.db.models import F
>>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
>>> product.number_sold = F('number_sold') + 1
>>> product.save()
此方法不使用数据库中的初始值。相反,它使数据库根据执行save()时的当前值进行更新。
保存对象后,必须重新加载对象才能访问应用于更新字段的实际值:
>>> product = Products.objects.get(pk=product.pk)
>>> print product.number_sold
42
答案 1 :(得分:0)
也许select_for_update QuerySet方法对您有所帮助。
文档的摘录:
所有匹配的条目将被锁定,直到事务块结束,这意味着将阻止其他事务更改或获取锁定。
通常,如果另一个事务已经对其中一个选定行获取了锁定,则查询将一直阻塞,直到锁定被释放。如果这不是您想要的行为,请调用select_for_update(nowait = True)。这将使呼叫无阻塞。如果另一个事务已经获取了冲突的锁,则在评估查询集时将引发DatabaseError。
请注意,这仅适用于Django开发版本(即> 1.3)。