设置后,SQLAlchemy急切/加入的加载是否可以被抑制?

Rus*_*uss 15 python sqlalchemy lazy-loading eager-loading

我有一个案例,大多数情况下,对象之间的关系是这样的,即预先配置对关系的热切(加入)负载是有意义的.但是现在我遇到了一种我真的不希望完成负载的情况.

我应该从关系中删除已加入的加载并更改所有相关查询以在查询位置(ick)加入,还是有某种方法可以在查询设置后抑制查询中的急切加载?

下面是一个示例,其中已在User-> Address关系上设置了预先加载.程序末尾的查询是否可以配置为不急于加载?

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("joe@example.com"),
                 Address("joeyjojojs@example.net")]
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
Run Code Online (Sandbox Code Playgroud)

Pav*_*pin 24

根据我的记忆,您可以逐个查询地覆盖属性的急切性.这会有用吗?

from sqlalchemy.orm import lazyload
joe = (s2.query(User)
    .options(lazyload('addresses'))
    .filter_by(name = "Joe").one())
for addr in joe.addresses:
    print addr.address
Run Code Online (Sandbox Code Playgroud)

查看文档.


kol*_*pto 6

您可以使用Query.options(raiseload('*'))Query.enable_eagerloads(False)

Query.enable_eagerloads(False)将禁用查询上的所有急切加载。就是说即使你放了ajoinedload()什么的,也不会被执行。

Query.options(raiseload('*'))将在每一列上安装一个raiseload加载器,确保它们没有延迟加载:而是引发异常。请注意,此模式适用于开发和测试环境,但在生产中可能具有破坏性。使其可选,如下所示:

Query.options(raiseload('*') if development else defaultload([]))
Run Code Online (Sandbox Code Playgroud)

另请注意,raiseload('*')仅适用于顶级关系。它不会在加入的实体上传播!如果您请求关系,则必须指定两次:

session.query(User).options(
    load_only('id'),
    joinedload(User.addresses).options(
        load_only('id'),
        raiseload('*')
    ),
    raiseload('*')
)
Run Code Online (Sandbox Code Playgroud)

另外,raiseload('*')仅适用于关系,不适用于列:) 对于列,请使用defer(..., raiseload=True)