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

min*_*hee 7 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())
Run Code Online (Sandbox Code Playgroud)

正如我所引用的,这些模型有一个关系,其backref命名为postsset-enabled(通过lazy='dynamic'选项).因为一些用户可能拥有大量帖子而大多数用户没有.

有了这些模型,我试过joinedloadUser.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.
Run Code Online (Sandbox Code Playgroud)

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

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

Sin*_*ion 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")
Run Code Online (Sandbox Code Playgroud)

  • 请注意,如果您在多对多配置中使用这样的多个关系,则需要将其中一个关系标记为 `passive_deletes=True`,否则会抛出 `StaleDataError`,因为 ORM 试图删除相同表通过这两种关系。http://stackoverflow.com/a/17242712/1255482 (2认同)