django中的一个计数器的primefaces增量

我试图在Django中自动递增一个简单的计数器。 我的代码如下所示:

from models import Counter from django.db import transaction @transaction.commit_on_success def increment_counter(name): counter = Counter.objects.get_or_create(name = name)[0] counter.count += 1 counter.save() 

如果我正确理解Django,这应该包含在一个事务中的函数,并使增量primefaces。 但这并不奏效,柜台更新中存在竞争状况。 这个代码怎么能成为线程安全的呢?

Django中的新function1.1

 Counter.objects.get_or_create(name = name) Counter.objects.filter(name = name).update(count = F('count')+1) 

或使用Fexpression式 :

 counter = Counter.objects.get_or_create(name = name) counter.count = F('count') +1 counter.save() 

在Django 1.4中, 支持SELECT … FOR UPDATE子句,使用数据库locking来确保没有错误地同时访问数据。

Django 1.7

 from django.db.models import F counter, created = Counter.objects.get_or_create(name = name) counter.count = F('count') +1 counter.save() 

保持简单,build立@Oduvan的答案:

 counter, created = Counter.objects.get_or_create(name = name, defaults={'count':1}) if not created: counter.count = F('count') +1 counter.save() 

这样做的好处是,如果在第一个语句中创build了对象,则不必进行任何更新。

如果您在设置时不需要知道柜台的价值,那么最好的答案肯定是您最好的select:

 counter = Counter.objects.get_or_create(name = name) counter.count = F('count') + 1 counter.save() 

这会告诉你的数据库在count的值上加1,这样做可以很好地完成,而不会阻塞其他的操作。 缺点是你无法知道你刚刚设置的数量。 如果两个线程同时打这个函数,他们都会看到相同的值,并会告诉数据库添加1.该数据库最终将加2如预期,但你不知道哪一个先走了。

如果您现在关心计数,则可以使用Emil Stenstrom引用的select_for_update选项。 以下是这个样子:

 from models import Counter from django.db import transaction @transaction.atomic def increment_counter(name): counter = (Counter.objects .select_for_update() .get_or_create(name=name)[0] counter.count += 1 counter.save() 

这将读取当前值并locking匹配的行直到事务结束。 现在只有一个工人可以阅读。 有关select_for_update的更多信息,请参阅文档 。

或者如果你只是想要一个计数器而不是一个持久对象,你可以使用在C中实现的itertools计数器.GIL将提供所需的安全性。

–Sai