加载柱
本节介绍有关加载列的其他选项。
延迟列加载
延迟的列加载只允许在直接访问时加载表的特定列,而不允许使用 Query
. 当您不想在不需要时将一个大文本或二进制字段加载到内存中时,此功能非常有用。单独的列可以自己惰性加载,也可以使用 deferred()
将它们标记为“延期”的函数。在下面的示例中,我们定义了一个映射,该映射将加载 .excerpt
和 .photo
在单独的单行select语句中,当每个属性首次在单个对象实例上引用时:
from sqlalchemy.orm import deferred from sqlalchemy import Integer, String, Text, Binary, Column class Book(Base): __tablename__ = 'book' book_id = Column(Integer, primary_key=True) title = Column(String(200), nullable=False) summary = Column(String(2000)) excerpt = deferred(Column(Text)) photo = deferred(Column(Binary))
经典映射总是使用 deferred()
在 properties
字典对照表绑定 Column
::
mapper_registry.map_imperatively(Book, book_table, properties={ 'photo':deferred(book_table.c.photo) })
延迟的列可以与一个“组”名称相关联,以便在第一次访问它们中的任何一个时将它们加载在一起。下面的示例定义了一个带有 photos
延期组。当一 .photo
访问后,所有三张照片都将加载到一个select语句中。这个 .excerpt
访问时将单独加载::
class Book(Base): __tablename__ = 'book' book_id = Column(Integer, primary_key=True) title = Column(String(200), nullable=False) summary = Column(String(2000)) excerpt = deferred(Column(Text)) photo1 = deferred(Column(Binary), group='photos') photo2 = deferred(Column(Binary), group='photos') photo3 = deferred(Column(Binary), group='photos')
延迟的列加载程序查询选项
在查询时,可以使用传递给 Query.options()
方法;最基本的查询选项是 defer()
和 undefer()
::
from sqlalchemy.orm import defer from sqlalchemy.orm import undefer query = session.query(Book) query = query.options(defer('summary'), undefer('excerpt')) query.all()
上面的“摘要”列在访问之前不会加载,“摘录”列将立即加载,即使它被映射为“延迟”列。
deferred()
用“group”标记的属性可以使用 undefer_group()
,以组名发送:
from sqlalchemy.orm import undefer_group query = session.query(Book) query.options(undefer_group('photos')).all()
跨多个实体延迟加载
为指定列延迟 Query
如果一次加载多个类型的实体,则可以使用类绑定属性而不是字符串名称更显式地指定deferral选项:
from sqlalchemy.orm import defer query = session.query(Book, Author).join(Book.author) query = query.options(defer(Author.bio))
列延迟选项也可能表明它们发生在不同的关系路径上,而这些路径本身往往是 eagerly loaded 带加载器选项。所有绑定到关系的加载器选项都支持链接到其他加载器选项上,包括为进一步的关系级别加载,以及在该路径上加载面向列的属性。例如,加载 Author
实例,然后加入热切加载 Author.books
为每个作者收集,然后对每个作者应用面向列的属性的延迟选项 Book
来自该关系的实体, joinedload()
加载器选项可以与 load_only()
选项(在本节后面描述)推迟所有 Book
列,但明确指定的列除外::
from sqlalchemy.orm import joinedload query = session.query(Author) query = query.options( joinedload(Author.books).load_only(Book.summary, Book.excerpt), )
如上所述的选项结构也可以以更复杂的方式组织,例如使用 Load.options()
方法,它允许将多个子选项同时链接到一个公共父选项。可以使用字符串名称和类绑定属性对象的任何组合:
from sqlalchemy.orm import defer from sqlalchemy.orm import joinedload from sqlalchemy.orm import load_only query = session.query(Author) query = query.options( joinedload(Author.book).options( load_only(Book.summary, Book.excerpt), joinedload(Book.citations).options( joinedload(Citation.author), defer(Citation.fulltext) ) ) )
1.3.6 新版功能: 补充 Load.options()
允许更容易地构造加载程序选项的层次结构。
将选项应用到路径的另一种方法是使用 defaultload()
功能。此函数用于指示加载器选项结构中的特定路径,而不实际在该级别设置任何选项,因此可以应用其他子选项。这个 defaultload()
函数可用于创建与上面使用的相同的结构 Load.options()
AS::
query = session.query(Author) query = query.options( joinedload(Author.book).load_only(Book.summary, Book.excerpt), defaultload(Author.book).joinedload(Book.citations).joinedload(Citation.author), defaultload(Author.book).defaultload(Book.citations).defer(Citation.fulltext) )
参见
与加载程序选项的关系加载 -以关系加载为目标
仅加载和通配符选项
ORM加载程序选项系统支持“通配符”加载程序选项的概念,其中加载程序选项可以通过星号传递。 "*"
指示特定选项应应用于映射类的所有适用属性。例如,如果我们想加载 Book
类,但只有“摘要”和“摘录”列,我们可以说:
from sqlalchemy.orm import defer from sqlalchemy.orm import undefer session.query(Book).options( defer('*'), undefer("summary"), undefer("excerpt"))
上面, defer()
选项使用通配符应用于 Book
类。然后, undefer()
选项用于“摘要”和“摘录”字段,以便它们是前面加载的唯一列。对上述实体的查询将只包括select中的“summary”和“excerpt”字段,以及ORM始终使用的主键列。
通过使用 load_only()
选项。这就是所谓的 排除的 选项,该选项将对所有列属性应用延迟行为,但名为的属性除外::
from sqlalchemy.orm import load_only session.query(Book).options(load_only(Book.summary, Book.excerpt))
具有多个实体查询的通配符和排除选项
通配符选项和排除选项,如 load_only()
只能应用于 Query
.以适应不太常见的情况 Query
一次返回多个主实体时,可能需要特殊的调用样式才能应用通配符或排除选项,即使用 Load
对象以指示延迟选项的起始实体。例如,如果我们正在装载 Book
和 Author
一下子, Query
如果我们尝试应用,会产生信息错误 load_only()
一次给两个人。使用 Load
看起来像:
from sqlalchemy.orm import Load query = session.query(Book, Author).join(Book.author) query = query.options( Load(Book).load_only(Book.summary, Book.excerpt) )
上面, Load
与排除选项一起使用 load_only()
因此,所有其他列的延迟只发生在 Book
阶级而不是 Author
类。再说一遍, Query
当实际需要上述调用样式时,对象应引发一条信息性错误消息,该调用样式描述了显式使用 Load
是必需的。
延迟列的Raiseload
1.4 新版功能.
这个 deferred()
装载机选项和相应的装载机策略也支持“raiseload”的概念,这是一种将提升的装载机策略 InvalidRequestError
如果访问属性时需要发出SQL查询才能加载。此行为相当于基于列的 raiseload()
关系加载功能,在 使用raiseload防止不需要的懒惰负载 . 使用 defer.raiseload
上的参数 defer()
如果引发了一个异常,则:
book = session.query(Book).options(defer(Book.summary, raiseload=True)).first() # would raise an exception book.summary
延迟的“raiseload”可以通过在映射器级别配置 deferred.raiseload
在 deferred()
,因此 undefer()
为使属性可用,需要:
class Book(Base): __tablename__ = 'book' book_id = Column(Integer, primary_key=True) title = Column(String(200), nullable=False) summary = deferred(Column(String(2000)), raiseload=True) excerpt = deferred(Column(Text), raiseload=True) book_w_excerpt = session.query(Book).options(undefer(Book.excerpt)).first()
列延迟API
Object Name | Description |
---|---|
defer(key, *addl_attrs, **kw) | 指示给定的列定向属性应延迟,例如,在访问之前不加载。 |
deferred(*columns, **kw) | 指示一个基于列的映射属性,默认情况下,除非访问该属性,否则不会加载该属性。 |
load_only(*attrs) | 指示对于特定实体,只应加载基于列的属性名的给定列表;所有其他属性名都将被延迟。 |
query_expression([default_expr]) | 指示从查询时SQL表达式填充的属性。 |
undefer(key, *addl_attrs) | 指示给定的面向列的属性应取消引用,例如,在整个实体的select语句中指定。 |
undefer_group(name) | 指示应取消对给定延迟组名称中的列的检索。 |
with_expression(key, expression) | 将临时SQL表达式应用于“deferred expression”属性。 |
- function sqlalchemy.orm.defer(key, *addl_attrs, **kw)
这个
Bundle
可用于查询一个命名空间下的列组。绑定允许将列分组在一起::
from sqlalchemy.orm import Bundle bn = Bundle('mybundle', MyClass.data1, MyClass.data2) for row in session.query(bn).filter(bn.c.data1 == 'd1'): print(row.mybundle.data1, row.mybundle.data2)
可以对包进行子类化,以便在获取结果时提供自定义行为。方法
Bundle.create_row_processor()
在查询执行时,给定语句对象和一组“行处理器”函数;当给定结果行时,这些处理器函数将返回单个属性值,然后可以将其调整为任何类型的返回数据结构。下面说明如何更换通常的Row
使用纯python字典返回结构:from sqlalchemy.orm import Bundle class DictBundle(Bundle): def create_row_processor(self, query, procs, labels): """Override create_row_processor to return values as dictionaries""" def proc(row): return dict( zip(labels, (proc(row) for proc in procs)) ) return proc
注解
这个
Bundle
构造只适用于列表达式。它不适用于使用映射的ORM属性relationship()
.在 1.0 版更改: 这个
proc()
Callable传递给create_row_processor()
自定义方法Bundle
类现在只接受一个“row”参数。上述包的结果将返回字典值:
bn = DictBundle('mybundle', MyClass.data1, MyClass.data2) for row in session.query(bn).filter(bn.c.data1 == 'd1'): print(row.mybundle['data1'], row.mybundle['data2'])
这个
Bundle
构造也集成到composite()
,用于在作为单个属性查询时将复合属性作为对象返回。