Reputation: 763
I have a problem of updating an instance in sqlalchemy. The instance attributes change after I modify them before the commit, but after I commit them they are back to the previous values. The session.is_modified(instance) too returns a False even after the data is updated.
Here is the code
from sqlalchemy.orm import sessionmaker, scoped_session
class Backend(object):
"""
"""
def __init__(self):
self._engine = create_engine("mysql://{0}:{1}@{2}/{3}?charset=utf8".format(DATABASE_CONFIGS.get('master').get('USER'),
DATABASE_CONFIGS.get('master').get('PASSWORD'),
DATABASE_CONFIGS.get('master').get('HOST'),
DATABASE_CONFIGS.get('master').get('DB_NAME')),
pool_recycle=3600,
pool_size= POOL_SIZE,
pool_timeout=1,
echo=False,
convert_unicode=True,
encoding='utf-8')
def get_session(self):
self._session = scoped_session(sessionmaker(bind=self._engine))
return self._session
class A():
attribute_meta = Column(JSONField(), nullable=True)
This is how the code is run:
def foo():
backend = Backend()
session = backend.get_session()
a = session.query(A).first()
a.attribute_meta = {'boo':'foo'}
session.add(a)
print("data before commit", a.attribute_meta)
print("is session modified", session.is_modified(a))
print("data after commit", a.attribute_meta)
session.commit()
session.close()
is session modified returns False
data before commit returns the modifed instance with appropriate data
data after commit returns the instance with its original value i.e. not modified
If I run the same code via shell, it works fine.
There are no post signals to the model that would alter the data too.
Turned on the echo=True but all is shows is just a select command that being fired in the db.
Anything I am missing?
Upvotes: 2
Views: 1107
Reputation: 763
The attribute I was trying to change was a JSON field and sqlalchemy doesn't check changes in a JSON field. That was the reason why those changes were there in the instance before a commit but the perished after it. The solution is to forcibly make the instance dirty i.e. make sqlalchemy purposefully check that attribute changes.
This is the code change -
from sqlalchemy.orm.attributes import flag_modified
flag_modified(bag, 'affiliate_meta') # Just because sqlalchemy doesnt track json field changes, check it before committing the session
Upvotes: 1