SQL Alchemy 中的过滤关系

PCL*_*PCL 4 python join sqlalchemy filter relationship

我有以下场景:

class Author(Base):
  __tablename__ = 'author'

  id    = Column(Integer, primary_key = True)
  name  = Column(String)

  books = relationship('Books', backref='author')


class Book(Base):
  __tablename__ = 'book'

  id    = Column(Integer, primary_key = True)
  title = Column(String)
Run Code Online (Sandbox Code Playgroud)

我想要做的是加载所有在书名中包含 SQL 的书的作者。IE

authors = session.query(Author)\
                 .join(Author.books)\
                 .filter(Book.title.like('%SQL%')\
                 .all()
Run Code Online (Sandbox Code Playgroud)

看起来很简单。

然后我想做的是迭代作者并展示他们的书。我希望在访问authors[0].books 时,它只会返回标题中包含“SQL”的书籍。但是,我将所有书籍分配给该作者。当我访问关系时,过滤器会应用于作者列表,但不会应用于他们的书籍。

我如何构建我的查询,以便如果我过滤关系(即书籍),当我访问该关系时,仍然应用过滤?

van*_*van 9

请阅读Routing Explicit Joins/Statements into Eagerly Loaded Collections。然后使用contains_eager您可以构建您的查询并获得您想要的内容:

authors = (
        session.query(Author)
        .join(Author.books)
        .options(contains_eager(Author.books)) # tell SA that we load "all" books for Authors
        .filter(Book.title.like('%SQL%'))
    ).all()
Run Code Online (Sandbox Code Playgroud)

请注意,您实际上是在欺骗 sqlalchemy,使其认为它已加载 的所有集合Author.books,因此您的会话将了解false有关世界真实状态的信息。