如何在SQLAlchemy中将joinedload / contains_eager用于启用查询的关系(lazy =“ dynamic”选项)

发布于 2021-01-29 15:25:32

我有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())

正如我所引用的,这些模型具有一种关系,其backref名称posts设置为启用查询(通过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.

有什么办法可以解决这种情况?我都需要同时具备以下两个功能:

  • 有时User.posts可以切成薄片,以避免急于增加沉重的用户撰写的大量帖子。
  • 但是通常User.posts不应产生1 + N个查询。
关注者
0
被浏览
42
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    问题在于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")
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看