Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Commit changes for only one SQLAlchemy model instance when multiple have changed

I queried and changed several instances. I only want to commit the changes to one of them. However, all the changes are committed when I call db.session.commit(). Is there a way to save an object individually, object.save(), like Rails or Django?

rule_1 = Rule.query.filter(Rule.something.like(that_thing))
rule_1.change_message = "Duplicate"

rule_2 = Rule.query.filter(Rule.something.like(that_thing))
rule_2.change_message = "This is 2nd Duplicate Message"

rule_3 = Rule.query.filter(Rule.something.like(that_thing))
rule_3.change_message = "This is the THIRD  Duplicate Message"

# What I want
rule_3.save() 
like image 447
Vic Avatar asked May 12 '16 15:05

Vic


People also ask

How do you commit changes in SQLAlchemy?

commit() is basically 2 steps in one: Flushing - push changes from SQLAlchemy's in-memory representation to the database transaction buffer. Commit - persist changes from your database's transaction buffer into the database, ie inserting / updating / deleting.

Does commit close the Session SQLAlchemy?

after commit you can refresh the session and then close the session.

What is Sessionmaker in SQLAlchemy?

Advertisements. In order to interact with the database, we need to obtain its handle. A session object is the handle to database. Session class is defined using sessionmaker() – a configurable session factory method which is bound to the engine object created earlier.

What does Autoflush do in SQLAlchemy?

autoflush – The autoflush setting to use with newly created Session objects. autocommit – The autocommit setting to use with newly created Session objects. expire_on_commit=True – the Session. expire_on_commit setting to use with newly created Session objects.


1 Answers

SQLAlchemy uses the unit of work pattern, while Django, Rails, and many other ORMs use the active record pattern. What this means is that everything that belongs to one session acts as one unit.

What your issue reveals is not an issue with SQLAlchemy, but an issue with your workflow. If you didn't want to change those values, you shouldn't have changed them. If you change something by mistake, expunge it from the session rather than leaving it around.

rule1.change_message = 'changed rule 1'
db.session.expunge(rule1)
# no longer part of the session, will not be committed
# use db.session.add(rule1) to track it again

If you really, actually, definitely need separate units of work (you most likely don't), create separate sessions and use them to query the separate instances.

Flask-SQLAlchemy uses one session per context, so all your queries place the instances in the same session. The query parameter uses this default session. You can create separate sessions by calling create_session. Make sure to clean these sessions up manually.

session1 = db.create_session({})
rule1 = session1.query(Rule).filter_by(name='rule1').one()
rule1.message = 'message'

session2 = db.create_session({})
rule2 = session2.query(Rule).filter_by(name='rule2').one()
rule2.message = 'message'
session2.commit()  # only commits rule2

session1.close()
session2.close()
like image 102
davidism Avatar answered Sep 24 '22 01:09

davidism