OK, the first load is expected, because when you session.query(X).options(someload(X.y)), the query will load all the ".y" for objects that it finds already in the identity map, however it will not establish someload() as a new permanent option on that X going forward, so subsequent loads use the default loader. if session.query(X).options(someload(X.y)) actually created the new X, then the someload() option is permanently associated with it. I understand this is not completely clear but historically, all of these loader options were just optimizations and it wasn't the end of the world if in some refresh circumstances, they didn't take effect. however with lazy='raise' it's a much bigger source of confusion.
There's an additional issue which is that in current 1.3 series, the call to refresh() does not make use of the loaders that were applied to the object . So for current releases, it still wont work for you; the load after the refresh() will fail even if the X was just loaded. However for 1.4 , it will work, due to https://docs.sqlalchemy.org/en/14/changelog/migration_14.html#change-1763 . short answer is that in 1.3 if you are using lazy="raise", the object won't really have flexibility in being able to actually load that attribute other than accessing it with a query. if you want, you can use this pattern, which should work everywhere: session.query(Group).populate_existing().options(lazyload(Group.users)).get(group.id) that also will apply the lazyload() option to the Group object permanently unless populate_existing() is used on it again. On Wed, Sep 25, 2019, at 3:57 PM, Mike Bayer wrote: > what you are seeing is somewhat backwards due to what might be a bug. in the > example you have, *both* calls to group.users should be raising, because this > object is already present in the identity map so your lazyload() option > should not affect this already-present Group object. > > if you load the Group newly into a new Session, or session.close() the one > you have, then the lazyload() option is associated with the Group and it will > lazy load every time for the lifespan of that object. > > I'm not sure yet why the lazyload() is somehow taking effect for the first > group.users in your example, though. it's not supposed to. > > > > On Wed, Sep 25, 2019, at 1:07 PM, Marat Sharafutdinov wrote: >> from sqlalchemy import Column, ForeignKey, Integer, create_engine >> from sqlalchemy.ext.declarative import declarative_base >> from sqlalchemy.orm import lazyload, relationship, sessionmaker >> >> Base = declarative_base() >> >> >> class Group(Base): >> __tablename__ = 'groups' >> >> id = Column(Integer, primary_key=True) >> >> users = relationship('User', lazy='raise') >> >> >> class User(Base): >> __tablename__ = 'users' >> >> id = Column(Integer, primary_key=True) >> group_id = Column(Integer, ForeignKey('groups.id')) >> >> >> engine = create_engine('sqlite:///:memory:', echo=True) >> Base.metadata.create_all(engine) >> >> Session = sessionmaker(bind=engine) >> session = Session() >> >> group = Group() >> session.add(group) >> session.commit() >> >> group = session.query(Group).options(lazyload(Group.users)).first() >> print('SUCCESS', group.users) >> session.refresh(group) >> print('FAILURE', group.users) >> >> Is `session.expire(group)` is the only way to reload collections and related >> items? >> >> -- >> SQLAlchemy - >> The Python SQL Toolkit and Object Relational Mapper >> >> http://www.sqlalchemy.org/ >> >> To post example code, please provide an MCVE: Minimal, Complete, and >> Verifiable Example. See http://stackoverflow.com/help/mcve for a full >> description. >> --- >> You received this message because you are subscribed to the Google Groups >> "sqlalchemy" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to sqlalchemy+unsubscr...@googlegroups.com. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/sqlalchemy/43ce8eb9-367d-43da-a371-0fa5e157e0de%40googlegroups.com >> >> <https://groups.google.com/d/msgid/sqlalchemy/43ce8eb9-367d-43da-a371-0fa5e157e0de%40googlegroups.com?utm_medium=email&utm_source=footer>. > > > -- > SQLAlchemy - > The Python SQL Toolkit and Object Relational Mapper > > http://www.sqlalchemy.org/ > > To post example code, please provide an MCVE: Minimal, Complete, and > Verifiable Example. See http://stackoverflow.com/help/mcve for a full > description. > --- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to sqlalchemy+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/sqlalchemy/d8864771-f2ec-48d4-a5fe-e7798926666e%40www.fastmail.com > > <https://groups.google.com/d/msgid/sqlalchemy/d8864771-f2ec-48d4-a5fe-e7798926666e%40www.fastmail.com?utm_medium=email&utm_source=footer>. -- SQLAlchemy - The Python SQL Toolkit and Object Relational Mapper http://www.sqlalchemy.org/ To post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description. --- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/ba781a08-31ff-496a-afdf-adb37ba90841%40www.fastmail.com.