get_history() call on relationship may interfere with other attributes' histories

Issue #3577 resolved
Roman Z. created an issue

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)

  1. Roman Z. reporter

    Thanks for your quick answer.

    What if I need the value of get_history(u, 'tags') (non-passive) too?

  2. Mike Bayer 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.

  3. Log in to comment