Arjunsingh
Arjunsingh

Reputation: 763

Data not being updated in sqlalchemy session

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

Answers (1)

Arjunsingh
Arjunsingh

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

Related Questions