2014-02-21 4 views
1

У меня есть следующий сценарий:Фильтрация отношений в SQL алхимии

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 в каждой книге, чтобы собрать книги, написанные одним и тем же автором вместе.

Смежные вопросы