对于我们的博客平台,我们有一个“文章”模型,其中包含“更新的”日期时间字段:
class Article(models.Model):
updated = models.DateTimeField(null=True, blank=True)
...
当文章在24小时内第一次被任何访问者打开时,我们会对不同的模型字段进行一些耗时的计算,然后将模型保存到数据库中。有了这个,我们还将“updated”字段更新为当前的datetime.now()。
if (datetime.now() - article.updated).days > 1:
# do some time consuming calculations
article.updated = datetime.now()
article.save()
当或多或少同时请求文章时,第一个请求上的耗时操作尚未完成,但是,导致每天一次的操作再次在同一个对象上启动(article.updated仍然是旧的值)。是否可以在开始计算之前另外调用article.save()?或者这个数据从保存到数据库推迟到请求完成之后?
答案 0 :(得分:2)
简短版本:
@transaction.commit_on_success
def update_article( article_id ):
article = Article.objects.select_for_update().get( pk = article_id )
if (datetime.now() - article.updated).days > 1:
# do some time consuming calculations
article.updated = datetime.now()
article.save()
select_for_update()
锁定数据库行(ID为article_ID的文章)。
该行在交易结束时解锁,位于
自update_article()
包裹@transaction.commit_on_success
以来函数的结尾。
诗 :自Django 1.4起可用
答案 1 :(得分:1)
使用Django 1.4中引入的查询集select_for_update,它在数据库中执行行级锁定。所有匹配的条目将被锁定,直到事务块结束,这意味着将阻止其他事务更改或获取锁定。有一些特定于datgabase后端的陷阱,所以在完全依赖它之前一定要读取并测试它。
独立于实现的其他一些方法是将模型自定义为具有locked
布尔属性。不是很整洁但是可行的解决方案。见What is the simplest way to lock an object in Django
答案 2 :(得分:1)
一些建议: