如何在SQLAlchemy中使用joinedload / contains_eager来启用查询的关系(lazy ='dynamic'选项)

时间:2011-08-04 03:16:06

标签: python sqlalchemy

我有SQLAlchemy声明的以下模型类:

class User(Base):
    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False, unique=True)
    created_at = Colmn(DateTime, nullable=False, default=func.now())

class Post(Base):
    id = Column(Integer, primary_key=True)
    user_id = Column(Integer, ForeignKey(User.id), nullable=False)
    user = relationship(User, backref=backref('posts', lazy='dynamic'))
    title = Column(String, nullable=False)
    body = Column(Text, nullable=False)
    created_at = Colmn(DateTime, nullable=False, default=func.now())

正如我所引用的,这些模型有一个关系,其名为posts的backref设置为启用查询(通过lazy='dynamic'选项)。因为一些用户可能拥有大量帖子而大多数用户没有。

使用这些模型,我为joinedload尝试了User.posts,但我遇到了错误:

>>> users = session.query(User).options(joinedload(User.posts))[:30]
Traceback (most recent call last):
  ...
InvalidRequestError: 'User.posts' does not support object population - eager loading cannot be applied.

有没有办法解决这种情况?我需要遵循两个功能:

  • 有时可以对User.posts进行切片,以避免因重度用户撰写的大量帖子而急切加载。
  • 但通常User.posts不应生成1 + N个查询。

1 个答案:

答案 0 :(得分:16)

问题是帖子User上的属性是动态关系;它应该返回一个Query对象。财产无法知道或安全地沟通,这次所有相关项目都已加载。

简单的解决方法是使用两个属性,一个使用正常的延迟加载行为(您可以设置为对有意义的特定查询进行急切加载),另一个始终返回动态关系。

class User(Base):
    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False, unique=True)
    created_at = Colmn(DateTime, nullable=False, default=func.now())

class Post(Base):
    id = Column(Integer, primary_key=True)
    user_id = Column(Integer, ForeignKey(User.id), nullable=False)
    user = relationship(User, backref=backref('posts'))
    title = Column(String, nullable=False)
    body = Column(Text, nullable=False)
    created_at = Colmn(DateTime, nullable=False, default=func.now())

User.post_query = relationship(Post, lazy="dynamic")