SQLModel Session exercise¶
Adapted from Drew's slack example
from chowda.db import init_db
from tests.factories import *
init_db()
Create a new Batch from factory¶
batch = BatchFactory.create()
Grab the session the Batch was created with for inspection.¶
from sqlmodel import Session
session = Session.object_session(batch)
Change something on the batch¶
batch.description = "exceedingly jolly"
View the changes that have yet to be committed to the db¶
print('session.dirty = ', session.dirty)
# => session.dirty = IdentitySet([Batch(description='foo')])
session.dirty = IdentitySet([Batch(description='exceedingly jolly')])
Commit the changes to the db.¶
Note that we do not have to call session.add(batch) since the Batch instance is already attached to the session.
session.commit()
Verify there are no other pending changes.¶
print('session.dirty = ', session.dirty)
# => IdentitySet([])
session.dirty = IdentitySet([])
Use a contextual session¶
(called "db") to grab a separate copy of the batch and verify it has the change.
from sqlmodel import select
with Session(engine) as db:
batch_copy = db.exec(select(Batch).where(Batch.id == batch.id)).first()
print('batch_copy.description = ', batch_copy.description)
# => foo
batch_copy.description = exceedingly jolly and effortlessly charming and elaborately loquacious
Note that since we grabbed batch_copy using a contextual session, and that context has ended, so has the session, and the object is currently unattached to any session.
print('seesion for batch_copy = ', Session.object_session(batch_copy))
# => None
seesion for batch_copy = None
Now change batch_copy.descripiton,¶
save it with a contextual session, and see how it affected or original Batch instance, which is still alive and attached to the session it was created with.
batch_copy.description += " and effortlessly charming"
with Session(engine) as db:
db.add(batch_copy)
db.commit()
NOTE: after committing changes to batch_copy using contextual session in this way,¶
trying to access attributes on the object like batch_copy.description raises an error:
Instance <Batch at 0x107b84e10> is not bound to a Session; attribute refresh operation cannot proceed
with Session(engine) as db:
db.add(batch_copy)
print('batch_copy.description = ', batch_copy.description)
# => batch_copy.description = exceedingly jolly and effortlessly charming
batch_copy.description = exceedingly jolly and effortlessly charming
Confirm that our original Batch instance still has the old description¶
print('batch.description before refresh = ', batch.description)
# => batch.description before refresh = exceedingly jolly
batch.description before refresh = exceedingly jolly
Refresh the original Batch instance¶
and check the description again
session.refresh(batch)
print('batch.description after refresh = ', batch.description)
# => batch.description after refresh = exceedingly jolly and effortlessly charming
batch.description after refresh = exceedingly jolly and effortlessly charming
Now let's edit batch.description
and batch_copy.description
¶
and update them both independently to see what happens.
batch.description += " and fantastically flatulent"
save the first edit¶
session.commit()
save the second edit¶
with Session(engine) as db:
batch_copy.description += " and elaborately loquacious"
db.add(batch_copy)
db.commit()
print('batch_copy.description = ', batch_copy.description)
# => batch_copy.description = exceedingly jolly and effortlessly charming and elaborately loquacious
batch_copy.description = exceedingly jolly and effortlessly charming and elaborately loquacious
Unsurprisingly, the 2nd save wins.¶
The changes saved in original Batch instance with it's original session get overwritten by this one.