2010-07-04 4 views
4

나는 다음 코드 조각은이 모델의 방법을 저장 재정의 한 :장고 롤백 트랜잭션

@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이 하나씩 증가하지만,있는 경우입니다 예외는 트랜잭션 롤백 (즉, self.qa.vote_down_count + = 1이 데이터베이스에서 커밋되지 않음을 의미)하는 슈퍼 (자체) 저장 메소드에서 발생합니다.

실제 동작은 다음과 같습니다. self.qa.vote_down_count + = 1은 IntegrityError 예외가 수퍼 (자체) 저장에서 발생하더라도 데이터베이스에 커밋됩니다.

아무튼?

+0

왜 처음에는 커밋을하고 마지막에는 다시 커밋할까요? –

+0

커밋 된 트랜잭션과 이전에 온 모든 것을 커밋하도록하지 않겠습니까? –

+0

이것은 사용중인 데이터베이스에 크게 의존 할 것입니다 .Postgres 8.0+와 Oracle은 트랜잭션을 적절하게 지원합니다 .MySQL은 그다지 훌륭하게 플레이하지 못합니다. 대부분의 다른 데이터베이스는 전혀 지원하지 않습니다. 그래서 질문 하나는 "귀하의 DB가 실제로 트랜잭션을 지원합니까?" –

답변

4

이유는 단순히 수행

@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 필요하지 않을 수도 있으므로 대신 퍼팅, 그것을 할 의미하는 방법 the docs입니다 그것은보기에.

+1

작업의 순서를 변경 내 의견에 문제가 해결되지 않으면, 그것은 일어날 오류를 방지하지 않습니다, 다른 경우에는 self.qa.save() 전에해야합니다. commit_amually 데코레이터는 동작을 변경하지 않습니다. –

+1

나는 당신이 저를 도울 수있는 것처럼 문제가 있습니다. 이 링크에서 내 질문을 찾을 수 있습니다. https://stackoverflow.com/questions/29574699/how-can-i-save-the-whole-db-transaction-if-there-is-no-error-in-python @ mike-desimone – Krish

3

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) 
+0

savepoint_rollback과 savepoint_commit을 의미한다고 가정합니다. –

0

나는 Mike DeSimone의 대답이 맞는 것 같아.

데이터베이스에 관해서는 사용하는 MySQL 버전 (사용하는 경우)에 따라 데이터베이스가 트랜잭션을 지원하지 않는 MyISAM 엔진을 사용하는 테이블 일 수 있습니다.

은 그냥 MySQL의 쉘에서 실행 확인하려면 다음

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

당신은 이노에 테이블을 변경하고 MySQL의 설정에 이노 디비에 default_storage_engine 설정할 수 있습니다. (자세한 내용은 여기 : http://parasjain.net/2010/06/08/how-to-switch-to-innodb-database-in-mysql/

Postgres를 사용하는 것이 더 좋지만 MySQL/InnoDB를 사용하려면 순방향 참조를 사용하여 조명기를로드 할 수있는 해결 방법이 필요합니다. BugFix는 Django Trunk에 이미 있으며, 장고 1.3.1에 이식했습니다 (Django 1.3.1.1 on Github 참조).

관련 문제