【问题标题】:Undo `lazyload()` with the relationship default使用关系默认撤消 `lazyload()`
【发布时间】:2014-07-28 17:08:58
【问题描述】:

我有一个 Query 对象,最初配置为 lazyload() 模型上的所有关系:

query = session.query(Article).options(lazyload('author'))

是否可以将关系加载恢复为默认值?例如。该关系是用lazy='joined' 配置的,我希望查询具有joinedload() 行为而不显式使用joinedload()

我期待defaultload() 有这种行为,但实际上它没有:它引用查询默认值而不是关系默认值。所以我正在寻找一种resetload() 解决方案。


这样做的原因是因为我正在创建基于 JSON 的查询语法,除非用户明确命名,否则不应加载任何关系。

目前,我在所有未明确请求的关系上使用lazyload(),但想反过来:lazyload() 首先是所有关系,然后为其中一些关系覆盖它。

这会使代码更加简洁。

【问题讨论】:

    标签: python sqlalchemy relationship


    【解决方案1】:

    要明确一点:

    默认情况下,所有对象间的关系都是延迟加载的。

    http://docs.sqlalchemy.org/en/latest/orm/loading.html

    所以我们讨论的是这样一种情况,其中一个关系被专门标记为预先加载,然后查询被配置为延迟加载,然后您想要“覆盖覆盖”。

    options 的链接调用将覆盖之前的调用。我确实对此进行了一些测试。

    q = s.query(User)  # lazy loads 'addresses'
    q = s.query(User).options(contains_eager('addresses'))  # eager loads
    q = s.query(User).options(contains_eager('addresses'))\
            .options(lazyload('addresses'))  # lazy loads
    q = s.query(User).options(contains_eager('addresses'))\
            .options(lazyload('addresses'))\
            .options(contains_eager('addresses'))  # eager loads
    

    但是,听起来您只是在谈论恢复 lazyload 选项,而上述情况涉及对预加载的显式更改。

    defaultload 文档字符串说它的用例是链接到其他加载器选项,所以我认为它不相关。

    基于对源代码的浏览,我认为不支持这种行为。当您更新加载策略选项时,它会使用新的加载策略更新字典,我认为至少据我所知,仍然没有对旧策略的引用。

    您可以在.options(lazyload(...)) 之前保留对查询对象的引用,或者只选择在所有内容上使用或不使用延迟加载来生成查询。

    【讨论】:

    • 是的,看起来唯一的方法是手动进行,例如从列检查中获取默认的lazy 设置。谢谢!
    【解决方案2】:

    要强制所有内容延迟加载,忽略在关系上指定的内容,您可以使用'*' 目标。来自the docs

    影响查询中未另行指定的所有关系。这 通过将字符串 '*' 作为参数传递给 any 这些选项中的一个:

    session.query(Article).options(lazyload('*'))
    

    然后您可以为每个关系或关系链指定所需的任何负载类型。

    # not sure how you are mapping json data to relationships
    # once you know the relationships, you can build a list of them to load
    my_loads = [joinedload(rel) for rel in json_rel_data]
    query = session.query(Article).options(lazyload('*'), *my_loads)
    # query lazy loads **everything** except the explicitly set joined loads
    

    如果您出于查询目的加入关系,则可以在选项中使用contains_eager 而不是joinedload 来使用已加入的关系。

    my_eagers = [contains_eager(rel) for rel in json_rel_joins]
    my_loads = [joinedload(rel) for rel in json_rel_loads]
    query = session.query(Article
    ).join(*json_rel_joins
    ).options(lazyload('*'), *my_eagers, *my_loads)
    

    【讨论】:

      猜你喜欢
      • 2010-10-27
      • 1970-01-01
      • 2022-07-27
      • 2010-10-17
      • 2018-12-05
      • 2021-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多