代码之家  ›  专栏  ›  技术社区  ›  will.i.am

save方法中的django回滚事务

  •  5
  • will.i.am  · 技术社区  · 14 年前

    我有以下代码覆盖模型的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\u down\u count+=1被提交到数据库,即使超级(self)save引发IntegrityError异常。

    3 回复  |  直到 14 年前
        1
  •  6
  •   Mike DeSimone    14 年前

    为什么不干脆做:

    @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()
    

    这是怎么回事 the docs 暗示这样做,尽管他们说在视图函数中这样做,所以您可能不需要 @transaction.commit_manually save() 方法,而不是将其放在视图上。

        2
  •  3
  •   Aldarund    14 年前

    尝试使用 savepoints

    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)
    
        3
  •  1
  •   Kee    13 年前

    我认为迈克·德西蒙的答案是对的。

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

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

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

    (详情如下: http://parasjain.net/2010/06/08/how-to-switch-to-innodb-database-in-mysql/

    在那之后,交易就可以进行了。最好使用Postgres,但是如果您想使用MySQL/InnoDB,那么您可能需要一个解决方法来加载带有前向引用的fixture(这个错误修复已经存在于Django Trunk中,我还将它移植到Django 1.3.1,请参阅) Django 1.3.1.1 on Github