Created
December 18, 2012 17:20
-
-
Save charlax/4329926 to your computer and use it in GitHub Desktop.
Keeping deletion atomic in spite of model method calling `commit()`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from sqlalchemy import Column, Integer, Unicode | |
from sqlalchemy import create_engine | |
from sqlalchemy.orm import sessionmaker, scoped_session | |
from sqlalchemy.ext.declarative import declarative_base | |
Base = declarative_base() | |
Session = scoped_session(sessionmaker()) | |
class User(Base): | |
__tablename__ = 'users_test_transaction' | |
id = Column(Integer, primary_key=True) | |
name = Column(Unicode(200)) | |
password = Column(Unicode(200)) | |
def delete_password(self): | |
self.password = "" | |
# Not sure if this is right, but my code has a lot of commit in a | |
# model's method. This prevents me from using begin_nested(). | |
Session.commit() | |
def delete(self): | |
self.delete_password() | |
raise TypeError("Nothing") | |
self.name = "Deleted" | |
Session.commit() | |
# Fake view | |
def delete_user(user): | |
# I would like this function to happen in a transaction, so that if | |
# any exception is raised in delete, it rolls back everything. Problem is, | |
# user.delete() might directly or inderectly call commit(). | |
try: | |
user.delete() | |
except: | |
# Because there's a commit in delete_password, this rollback will do | |
# nothing. | |
Session.rollback() | |
def main(): | |
# Create the table | |
engine = create_engine('', echo=True) | |
Base.metadata.drop_all(engine) | |
Base.metadata.create_all(engine) | |
Session.configure(bind=engine) | |
# Create the user | |
user = User(name="First Last", password="passwhatever") | |
Session.add(user) | |
Session.commit() | |
# Delete it | |
delete_user(user) | |
user = Session.query(User).first() | |
assert user.name != "Deleted" | |
# This raises an exception because a commit prevented the full rollback. | |
assert user.password != "" | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment