- changed status to resolved
get_history() call on relationship may interfere with other attributes' histories
I currently try to get the original values of certain attributes in before_commit
. For that I call get_history
on some attributes. It seems that the history of all attributes is flushed, when the history of the relationship is loaded.
Here is a full test-script.
from sqlalchemy import create_engine, Column, String, Integer
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import backref, relationship, sessionmaker
from sqlalchemy.orm.attributes import get_history, History
from sqlalchemy.sql.schema import ForeignKey
Base = declarative_base()
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String)
class Tag(Base):
__tablename__ = 'tag'
id = Column(Integer, primary_key=True)
user_id = Column(ForeignKey(User.id))
tag = Column(String)
user = relationship(User, backref=backref('tags'))
engine = create_engine('sqlite:///:memory:', echo=True)
Base.metadata.create_all(engine)
session = sessionmaker(bind=engine)()
u = User(name='old')
session.add(u)
session.commit()
getattr(u, 'name')
u.name = 'new'
assert get_history(u, 'name') == History(['new'], (), ['old'])
get_history(u, 'tags')
# Fails: History(added=(), unchanged=['new'], deleted=())
assert get_history(u, 'name') == History(['new'], (), ['old'])
It seems that the call get_history(u, 'tags')
leads to the update being flushed.
Is there any way to consistently get the original value of an attribute from before the transaction has started?
This was tested using 1.0.8.
Comments (4)
-
repo owner -
repo owner to clarify, your get_history() call is emiting a Query which is then autoflushing. Alternatively, block it within session.no_autoflush: http://docs.sqlalchemy.org/en/rel_1_0/orm/session_api.html?highlight=no_autoflush#sqlalchemy.orm.session.Session.no_autoflush
-
reporter Thanks for your quick answer.
What if I need the value of
get_history(u, 'tags')
(non-passive) too? -
repo owner just turn off autoflush with the no_autoflush context manager. for critical sections where you need to inspect things with knowledge of the database, this is appropriate.
- Log in to comment
use the inspect api and use the .history attribute: http://docs.sqlalchemy.org/en/rel_1_0/orm/internals.html?highlight=instancestate#sqlalchemy.orm.state.AttributeState.history or if using get_history() send the correct PASSIVE flag through: http://docs.sqlalchemy.org/en/rel_1_0/orm/session_api.html#sqlalchemy.orm.attributes.get_history.params.passive