繁体   English   中英

save方法中的django回滚事务

[英]django rollback transaction in save method

我有以下代码覆盖模型的save方法:

@transaction.commit_on_success
def save(self, *args, **kwargs):

    try:
        transaction.commit()
        self.qa.vote_down_count += 1
        self.qa.save()

        super(self.__class__, self).save(*args, **kwargs)

    except:
        transaction.rollback()
        raise
    else:
        transaction.commit()

预期的行为是:self.qa属性vote_down_count加1,但如果在super(self)save方法中发生任何异常,则事务回滚(这意味着self.qa.vote_down_count + = 1未在数据库中提交) )。

实际行为是:即使IntegrityError异常从super(self)save引发,self.qa.vote_down_count + = 1也会提交到数据库。

有没有?

为什么不简单地做:

@transaction.commit_manually
def save(self, *args, **kwargs):
    try:
        super(self.__class__, self).save(*args, **kwargs)
        self.qa.vote_down_count += 1
        self.qa.save()
    except:
        transaction.rollback()
        raise
    else:
        transaction.commit()

这就是文档暗示这样做的方式,虽然他们说在你的视图函数中这样做,所以你可能不需要在save()方法上使用@transaction.commit_manually ,而是将它放在视图上。

尝试使用保存点 像这样的东西:

def save(self, *args, **kwargs):

try:
    sid = transaction.savepoint()
    self.qa.vote_down_count += 1
    self.qa.save()

    super(self.__class__, self).save(*args, **kwargs)

except:
    transaction.rollback(sid)
    raise
else:
    transaction.commit(sid)

我认为Mike DeSimone的答案是正确的。

关于数据库,根据您使用的MySQL版本(如果使用它),可能是您的数据库使用MyISAM引擎,不支持事务。

要检查它只是在mysql shell中运行:

SELECT TABLE_NAME, 
    ENGINE 
    FROM information_schema.TABLES 
    where TABLE_SCHEMA = 'your_db_name' ;

您可以将表更改为InnoDB,并在MySQL配置中将default_storage_engine设置为innodb。 (详情请访问: http//parasjain.net/2010/06/08/how-to-switch-to-innodb-database-in-mysql/

之后交易应该有效。 最好使用Postgres,但是如果你想使用MySQL / InnoDB,那么你可能需要一个解决方法来加载具有前向引用的fixture(BugFix已经存在于Django Trunk中,我也将它移植到Django) 1.3.1,参见Github上的Django 1.3.1.1 )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM