Hi, I'm trying to implement soft deletion in my app. I'd like to keep things atomic so that if an error happens during the soft deletion process, I don't get half deleted stuff.
Here is a simplified view of my code (full working example here: https://gist.github.com/4329926): 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() So the problem here is that the rollback does nothing, because there's a commit in the delete_password method (in this example there's only method called, in reality I have multiple methods). I think having stuff being committed in a model's method is antipattern (is it?) but I'd like to know if there's a simple way to get the desired behavior. I tried: 1. Manually setting a savepoint (Session.execute("SAVEPOINT soft_delete")). But commit in delete_password closes the connection so the savepoint is lost. 2. Using begin_nested and begin(subtransactions=True), but commit in delete_password closes the context. 3. I thought of using autocommit=True but it seems it's not recommended (and I'm not sure to understand all the implications of this), or creating an external transaction<http://docs.sqlalchemy.org/en/latest/orm/session.html#joining-a-session-into-an-external-transaction> but the example in the doc is only for tests so I'm not sure if it's antipattern too. Also, getting access to the engine would require quite a small refactor of my app. Any idea? Should I get rid of the commit in the model's methods (or add a do_not_commit arg to the function)? I wish there were a simple solution that do not require changing the model methods. Thanks, Charles -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To view this discussion on the web visit https://groups.google.com/d/msg/sqlalchemy/-/Mgi5ByBSuLMJ. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
