SQLAlchemy 急切/连接负载一旦设置就可以被抑制吗?
我遇到过这样的情况:大多数时候,对象之间的关系是这样的,在关系上预先配置急切(连接)负载是有意义的。然而现在我遇到的情况是我真的不希望完成急切的负载。
我是否应该从关系中删除连接负载并将所有相关查询更改为在查询位置连接(ick),或者是否有某种方法可以在设置后抑制查询中的急切负载?
下面是一个在 User->Address 关系上设置急切加载的示例。程序末尾的查询可以配置为NOT eager load吗?
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
import sqlalchemy.orm as orm
##Set up SQLAlchemy for declarative use with Sqlite...
engine = sa.create_engine("sqlite://", echo = True)
DeclarativeBase = declarative_base()
Session = orm.sessionmaker(bind = engine)
class User(DeclarativeBase):
__tablename__ = "users"
id = sa.Column(sa.Integer, primary_key = True, autoincrement = True)
name = sa.Column(sa.String, unique = True)
addresses = orm.relationship("Address",
lazy = "joined", #EAGER LOAD CONFIG IS HERE
)
def __init__(self, Name):
self.name = Name
class Address(DeclarativeBase):
__tablename__ = "addresses"
id = sa.Column(sa.Integer, primary_key = True, autoincrement = True)
address = sa.Column(sa.String, unique = True)
FK_user = sa.Column(sa.Integer, sa.ForeignKey("users.id"))
def __init__(self, Email):
self.address = Email
##Generate data tables...
DeclarativeBase.metadata.create_all(engine)
##Add some data...
joe = User("Joe")
joe.addresses = [Address("[email protected]"),
Address("[email protected]")]
s1 = Session()
s1.add(joe)
s1.commit()
## Access the data for the demo...
s2 = Session()
#How to suppress the eager load (auto-join) in the query below?
joe = s2.query(User).filter_by(name = "Joe").one() # <-- HERE?
for addr in joe.addresses:
print addr.address
I've got a case where most of the time the relationships between objects was such that pre-configuring an eager (joined) load on the relationship made sense. However now I've got a situation where I really don't want the eager load to be done.
Should I be removing the joined load from the relationship and changing all relevant queries to join at the query location (ick), or is there some way to suppress an eager load in a query once it is set up?
Below is an example where eager loading has been set up on the User->Address relationship. Can the query at the end of the program be configured to NOT eager load?
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
import sqlalchemy.orm as orm
##Set up SQLAlchemy for declarative use with Sqlite...
engine = sa.create_engine("sqlite://", echo = True)
DeclarativeBase = declarative_base()
Session = orm.sessionmaker(bind = engine)
class User(DeclarativeBase):
__tablename__ = "users"
id = sa.Column(sa.Integer, primary_key = True, autoincrement = True)
name = sa.Column(sa.String, unique = True)
addresses = orm.relationship("Address",
lazy = "joined", #EAGER LOAD CONFIG IS HERE
)
def __init__(self, Name):
self.name = Name
class Address(DeclarativeBase):
__tablename__ = "addresses"
id = sa.Column(sa.Integer, primary_key = True, autoincrement = True)
address = sa.Column(sa.String, unique = True)
FK_user = sa.Column(sa.Integer, sa.ForeignKey("users.id"))
def __init__(self, Email):
self.address = Email
##Generate data tables...
DeclarativeBase.metadata.create_all(engine)
##Add some data...
joe = User("Joe")
joe.addresses = [Address("[email protected]"),
Address("[email protected]")]
s1 = Session()
s1.add(joe)
s1.commit()
## Access the data for the demo...
s2 = Session()
#How to suppress the eager load (auto-join) in the query below?
joe = s2.query(User).filter_by(name = "Joe").one() # <-- HERE?
for addr in joe.addresses:
print addr.address
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
据我所知,您可以在逐个查询的基础上覆盖属性的渴望。这行得通吗?
请参阅文档。
You may override eagerness of properties on query-by-query basis, as far as I remember. Will this work?
See the docs.
您可以使用
Query.options(raiseload('*'))
或Query.enable_eagerloads(False)
。Query.enable_eagerloads(False)
将禁用查询上的所有预加载。也就是说,即使你放了一个joinedload()
什么的,它也不会被执行。Query.options(raiseload('*'))
将在每列上安装一个raiseload
加载器,确保它们不是延迟加载:而是引发异常。请注意,此模式适用于开发和测试环境,但在生产中可能具有破坏性。像这样将其设为可选:另请注意,
raiseload('*')
仅适用于顶级关系。它不会在加入的实体上传播!如果您请求关系,则必须指定两次:此外,
raiseload('*')
仅适用于关系,不适用于列:)对于列,请使用
defer( ..., raiseload=True)
You can use
Query.options(raiseload('*'))
orQuery.enable_eagerloads(False)
.Query.enable_eagerloads(False)
will disable all eager loading on the query. That is, even if you put ajoinedload()
or something, it won't be executed.Query.options(raiseload('*'))
will install araiseload
loader on every column, making sure they're not lazily loaded: an exception is raised instead. Note that this mode is fine for development and testing environments, but may be destructive in production. Make it optional like this:also note that
raiseload('*')
only works for top-level relationships. It won't spread on joined entities! If you request a relationship, you have to specify it twice:also,
raiseload('*')
only works for relationships, not columns :)For columns, use
defer(..., raiseload=True)