2014-02-21 91 views
1

我有以下情形:過濾關係

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) 

我想要做的就是加載誰擁有包含SQL在 標題一本書的所有作者。即

authors = session.query(Author)\ 
       .join(Author.books)\ 
       .filter(Book.title.like('%SQL%')\ 
       .all() 

似乎很簡單。

然後我想要做的是遍歷作者,並顯示他們的 書籍。我期望在訪問作者[0] .books時,它將僅返回 其標題中具有「SQL」的書籍。不過,我收到了所有分配給該作者的書籍 。當我訪問關係時,該過濾器應用於作者列表,但不適用於他們的作品列表 。

如何構建我的查詢,以便在篩選關係時(即 書籍),當我訪問該關係時,仍然應用篩選?

回答

2

請閱讀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() 

請注意,你實際上是在欺騙SQLAlchemy的,以爲它已加載的Author.books所有的集合,因此你會知道false有關世界真實狀態的信息。

1

總之,這是不可能的。 (如果是這樣,一個Author實例將取決於它如何被質疑,這沒有任何意義有不同的books屬性。)

你可以做的反而是查詢反向關係:

books = session.query(Book) \ 
       .filter(Book.title.like('%SQL%')) \ 
       .all() 

然後,您可以在每本書上訪問.author以收集由同一作者撰寫的書籍。