Release: 1.4.25 | Release Date: September 22, 2021

SQLAlchemy 1.4 Documentation

加载柱

本节介绍有关加载列的其他选项。

延迟列加载

延迟的列加载只允许在直接访问时加载表的特定列,而不允许使用 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 对象以指示延迟选项的起始实体。例如,如果我们正在装载 BookAuthor 一下子, 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.raiseloaddeferred() ,因此 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)

指示给定的列定向属性应延迟,例如,在访问之前不加载。

此函数是 Load 接口和支持方法链接和独立操作。

例如。::

from sqlalchemy.orm import defer

session.query(MyClass).options(
                    defer("attribute_one"),
                    defer("attribute_two"))

session.query(MyClass).options(
                    defer(MyClass.attribute_one),
                    defer(MyClass.attribute_two))

要在相关类上指定属性的延迟加载,可以一次指定一个令牌的路径,为链上的每个链接指定加载样式。若要保持链接的加载样式不变,请使用 defaultload() ::

session.query(MyClass).options(defaultload("someattr").defer("some_column"))

A Load 存在于某个路径上的对象可以具有 Load.defer() 多次调用,每个都将在同一父实体上操作:

session.query(MyClass).options(
                defaultload("someattr").
                    defer("some_column").
                    defer("some_other_column").
                    defer("another_column")
    )
参数
  • key -- 要延迟的属性。

  • raiseload -- 提升 InvalidRequestError 如果要从发出SQL加载列值。用于防止发出不需要的SQL。。版本添加::1.4。。另请参见: 延迟列的Raiseload

  • *addl_attrs -- 此选项支持将路径指定为一系列属性的旧0.8样式,现在由方法链接样式取代。…已弃用::0.9 * Advl defer() 已弃用,将在将来的版本中删除。请将方法链接与defaultLoad()一起使用以指示路径。

function sqlalchemy.orm.deferred(*columns, **kw)

指示一个基于列的映射属性,默认情况下,除非访问该属性,否则不会加载该属性。

参数
  • *columns -- 要映射的列。这通常是一个 Column 但是,为了支持在同一属性下映射的多个列,支持集合。

  • raiseload -- 如果布尔操作被引发为True,则表示发生异常。。版本添加::1.4。。另请参见: 延迟列的Raiseload

  • **kw -- 传递给的其他关键字参数 ColumnProperty .

function sqlalchemy.orm.query_expression(default_expr=<sqlalchemy.sql.elements.Null object>)

指示从查询时SQL表达式填充的属性。

参数

default_expr -- 可选的SQL表达式对象,如果以后不使用 with_expression() . E、 g.::来自sql炼金术.sql导入文本类C(基):#。。。my_expr=查询表达式(文本(1))。。版本添加::1.3.18

1.2 新版功能.

function sqlalchemy.orm.load_only(*attrs)

指示对于特定实体,只应加载基于列的属性名的给定列表;所有其他属性名都将被延迟。

此函数是 Load 接口和支持方法链接和独立操作。

示例-给定一个类 User 只加载 namefullname 属性::

session.query(User).options(load_only(User.name, User.fullname))

示例-给定关系 User.addresses -> Address ,为指定子查询加载 User.addresses 收集,但在每个 Address 对象仅加载 email_address 属性:

session.query(User).options(
        subqueryload(User.addresses).load_only(Address.email_address)
)

对于一个 Query 如果有多个实体,则可以使用 Load 施工人员:

   session.query(User, Address).join(User.addresses).options(
               Load(User).load_only(User.name, User.fullname),
               Load(Address).load_only(Address.email_address)
           )

.. note:: This method will still load a :class:`_schema.Column` even
   if the column property is defined with ``deferred=True``
   for the :func:`.column_property` function.

0.9.0 新版功能.

function sqlalchemy.orm.undefer(key, *addl_attrs)

指示给定的面向列的属性应取消引用,例如,在整个实体的select语句中指定。

未被检索的列通常在映射上设置为 deferred() 属性。

此函数是 Load 接口和支持方法链接和独立操作。

实例:

# undefer two columns
session.query(MyClass).options(undefer("col1"), undefer("col2"))

# undefer all columns specific to a single class using Load + *
session.query(MyClass, MyOtherClass).options(
    Load(MyClass).undefer("*"))

# undefer a column on a related object
session.query(MyClass).options(
    defaultload(MyClass.items).undefer('text'))
参数
  • key -- 属性未被检索。

  • *addl_attrs -- 此选项支持将路径指定为一系列属性的旧0.8样式,现在由方法链接样式取代。…已弃用::0.9 * Advl undefer() 已弃用,将在将来的版本中删除。请将方法链接与defaultLoad()一起使用以指示路径。

function sqlalchemy.orm.undefer_group(name)

指示应取消对给定延迟组名称中的列的检索。

在映射上未被检索的列设置为 deferred() 属性并包含“组”名称。

例如::

session.query(MyClass).options(undefer_group("large_attrs"))

要取消对相关实体的一组属性的传递,可以使用关系加载器选项(如 defaultload() ::

session.query(MyClass).options(
    defaultload("someattr").undefer_group("large_attrs"))

在 0.9.0 版更改: undefer_group() 现在特定于特定的实体加载路径。

function sqlalchemy.orm.with_expression(key, expression)

将临时SQL表达式应用于“deferred expression”属性。

此选项与 query_expression() 映射器级构造,指示应作为临时SQL表达式目标的属性。

例如。::

sess.query(SomeClass).options(
    with_expression(SomeClass.x_y_expr, SomeClass.x + SomeClass.y)
)

1.2 新版功能.

参数
  • key -- 属性未被检索。

  • expr -- 要应用于属性的SQL表达式。

注解

仅当目标对象为 当前未加载 在当前 Session 除非 Query.populate_existing() 方法。请参阅 作为映射属性的查询时间SQL表达式 了解完整的用法详细信息。

列束

这个 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() ,用于在作为单个属性查询时将复合属性作为对象返回。

Previous: ORM查询指南 Next: 关系加载技术