如何在SQLAlchemy中加载嵌套关系?

Mar*_*ann 6 python orm sqlalchemy lazy-loading

在我的Pyramid + SQLAlchemy网站上,我希望客户查看他已经放置的所有商品.Purchase有许多PurchaseOrder,PurchaseOrder有很多PurchaseOrderDetail.

我希望以优化的方式获取所有购买上下文(包括订单和详细信息),因此我正在研究SQLAlchemy加载策略.

我的模型声明如下所示:

class Purchase(Base):
    __tablename__ = 'purchase'
    __table_args__ = {'schema':'db','autoload':True}

    customer = relationship(Customer)
    billing_address = relationship(Address,primaryjoin="Address.AddressId==Purchase.BillingAddressId")
    shipping_address = relationship(Address,primaryjoin="Address.AddressId==Purchase.ShippingAddressId")
    orders = relationship(PurchaseOrder)

class PurchaseOrder(Base):
    __tablename__ = 'purchase_order'
    __table_args__ = {'schema':'db','autoload':True}

    company = relationship(Company)
    delivery_service = relationship(DeliveryService)
    details = relationship(PurchaseOrderDetail)

class PurchaseOrderDetail(Base):
    __tablename__ = 'purchase_order_detail'
    __table_args__ = {'schema':'db','autoload':True}

    product_variant = relationship(ProductVariant)
Run Code Online (Sandbox Code Playgroud)

我想要的是这种形式的东西:

    db_session = DBSession()
    p = db_session.query(Purchase).\
        options(joinedload_all(Purchase.customer,
                                Purchase.billing_address,
                                Purchase.shipping_address)
                ,subqueryload_all(Purchase.orders,
                                Purchase.orders.details)).all()
Run Code Online (Sandbox Code Playgroud)

但是,Purchase.orders.details不允许该部件并引发以下异常:

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "C:\apps\pyramid\lib\site-packages\sqlalchemy\orm\attributes.py", line 139, in __getattr__
    key)
AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object has an attribute 'details'
Run Code Online (Sandbox Code Playgroud)

所以,我的问题是:

  1. 查询Purchase模型时如何加载PurchaseOrderDetails?
  2. 这是获得所有购买conext的最佳方式吗?

提前致谢

use*_*045 10

我的批评是因为我不经常在Stack Overflow中发表评论所以我不确定这是否应该发布.

仅供参考,sqlalchemy.orm.subqueryload_all已被弃用(自0.9.0版本起).

他们现在希望您使用方法链接.

session.query(MyClass).options(
    subqueryload("someattribute").subqueryload("anotherattribute")
)
Run Code Online (Sandbox Code Playgroud)


van*_*van 6

subqueryload_all(...)查询的一部分更改为以下两个选项之一将完成以下任务:

# option-1:
subqueryload_all(
    'orders.details', # @note: this will load both *orders* and their *details*
    )

# option-2:
subqueryload_all(
    Purchase.orders,       # @note: this will load orders
    PurchaseOrder.details, # @note: this will load orders' details
    )
Run Code Online (Sandbox Code Playgroud)

sqlalchemy.orm.subqueryload_all在列出的示例中,文档非常清楚.