noload is how you'd disable implicit loading. As far as throwing
on a lazyload, the easiest way is just to detach the objects from
their parent Session so they no longer have any connectivity using
session.expunge(object), but then you're no longer in the session.
Otherwise, it seems the problem you are actually trying to solve is
raising on unexpected SQL. lazy loading of relationships is not
the only thing that goes on, there are loads of unloaded columns,
columns that had server defaults emitted on the last flush, loads of
joined-inheritance rows, all kinds. this is why the best
approach is to just do real profiling of your applications using SQL
logging, or perhaps using SQL events like before_execute() /
before_cursor_execute() so that you can build yourself a "with
assert_no_sql(session):" -style context manager for critical blocks
that should have no SQL emitted.
Guessing that's not what you want. Feel free to write your own
NoLoader that just raises, example:
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import properties
from sqlalchemy.orm import strategies
@properties.RelationshipProperty.strategy_for(lazy="raise")
class RaiseLoader(strategies.NoLoader):
"""note: this is *very SQLAlchemy 1.0 specific*!! it will need
to be reviewed for 1.1"""
def create_row_processor(
self, context, path, loadopt, mapper,
result, adapter, populators):
def invoke_no_load(state, dict_, row):
raise Exception("boom")
populators["new"].append((self.key, invoke_no_load))
Base = declarative_base()
class A(Base):
__tablename__ = 'a'
id = Column(Integer, primary_key=True)
bs = relationship("B", lazy="raise")
class B(Base):
__tablename__ = 'b'
id = Column(Integer, primary_key=True)
a_id = Column(ForeignKey('
a.id'))
e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)
s = Session(e)
s.add(A(bs=[B(), B()]))
s.commit()
a1 = s.query(A).first()
a1.bs # boom
send me a PR that includes tests and I can consider this for 1.1.