In SQLAlchemy, after creating a session, it is necessary to perform commit (), rollback (), and close () as needed.
Here, we will create a class that performs DB operations and summarize how to pass sessions.
In the following, it is assumed that the following model class exists.
models.py
class User(Base):
__tablename__="user" #Specify table name
id=Column(Integer, primary_key=True)
first_name=Column(String(255))
last_name=Column(String(255))
It is not good to make it like the following source code.
wrong_way.py
from models import User
class FirstName(object):
def update_first_name(self, user_id, first_name):
session=Session()
try:
user=session.query(User).filter(User.id==user_id).one() #id=user_Extract obj which is id
user.first_name=first_name #first_Change name
session.commit()
except:
session.rollback()
raise
class LastName(object):
def update_last_name(self, user_id, last_name):
session=Session()
try:
user=session.query(User).filter(User.id==user_id).one() #id=user_Extract obj which is id
user.first_name=first_name #last_Change name
session.commit()
except:
session.rollback()
raise
def run_my_program():
FirstName().update_first_name(1, "update_first_name")
LastName().update_last_name(1, "update_last_name")
Because the same session is not used in ʻupdate_first_name and ʻupdate_last_name in run_my_program.
"First_name was updated, but last_name was not."
This is because something like this happens.
Therefore, it can be solved by using the following source code.
right_way_1.py
from models import User
class FirstName(object):
def update_first_name(self, user_id, first_name, session):
user=session.query(User).filter(User.id==user_id).one()
user.first_name=first_name
class LastName(object):
def update_last_name(self, user_id, last_name, session):
user=session.query(User).filter(User.id==user_id).one()
user.first_name=first_name
def run_my_program():
session = Session()
try:
FirstName().update_first_name(session)
LastName().update_last_name(session)
session.commit()
except:
session.rollback()
raise
finally:
session.close()
By doing this, the same session will be used for ʻupdate_first_name and ʻupdate_last_name.
"Only one ran successfully"
The situation like this does not occur.
Next, we will introduce how to handle session using context manager.
As for the context manager, the following articles are very easy to understand and helpful, so the explanation is omitted here.
What is a Python context manager? The story I searched for
right_way_2.py
from models import User
from contextlib import contextmanager
@contextmanager
def session_scope():
session = Session() # def __enter__
try:
yield session #Pass session with as
session.commit() #If nothing happens, commit()
except:
session.rollback() #Rollback if error occurs()
raise
finally:
session.close() #Either way, it will eventually close()
class FirstName(object):
def update_first_name(self, user_id, first_name, session):
user=session.query(User).filter(User.id==user_id).one()
user.first_name=first_name
class LastName(object):
def update_last_name(self, user_id, last_name, session):
user=session.query(User).filter(User.id==user_id).one()
user.first_name=first_name
def run_my_program():
with session_scope() as session:
FirstName().update_first_name(session)
LastName().update_last_name(session)
This article was written with reference to the following information. -Official Documents (Session Basics) · [What is a Python context manager? The story I investigated (https://blog.mtb-production.info/entry/2018/04/10/183000)
Recommended Posts