Colton Allen
Colton Allen

Reputation: 3060

Rolling back after a failed transaction

I have an operation where a parent model needs to be created with some amount of child models. If the creation of any of these instances fails, the whole thing needs to be canceled. The parent model and its children should not exist in the database if an error is raised.

The code I have:

transaction = db.engine.connect().begin()

try:
    parent = ParentModel()
    db.session.add(parent)
    db.session.commit()

    child = ChildModel(parent_id=parent.id)
    db.session.add(child)
    db.session.commit()

    # An error occurs.  We need to rollback the saved parent model.
    raise HTTPException() # from werkzeug
except:
    transaction.rollback()

transaction.commit()

My test:

def test(self):
    # call the above operation
    ParentModel.query.filter_by(id=1).first() # returns the parent model

Upvotes: 0

Views: 1389

Answers (1)

dirn
dirn

Reputation: 20719

Flask-SQLAlchemy turns on autocommit by default. In order to rollback a transaction, you need to turn it off. Instead of

db = SQLAlchemy(app)  # or whatever variation you use

use

db = SQLAlchemy(app, session_options={'autocommit': False})

This will allow you to add several objects to db.session before either committing or rolling back.

With this change, you can remove your references to transaction.

Upvotes: 2

Related Questions