2015-12-04 7 views
0

Я несколько разветвленная структура отношения (позволяет использовать пример базы данных сватовства - фактический случай является немного более сложным, к сожалению):Разветвленные отношения с SQLAlchemy

class Hobby(Base): 
    __tablename__ = 'hobby' 
    id = Column(Integer, primary_key=True) 
    hobby_name = Column(String(255, u'utf8_unicode_ci'), nullable=False) 

class Guy(Base): 
    __tablename__ = 'guy' 
    id = Column(Integer, primary_key=True) 
    name = Column(String(255, u'utf8_unicode_ci'), nullable=False) 

class Girl(Base): 
    __tablename__ = 'girl' 
    id = Column(Integer, primary_key=True) 
    name = Column(String(255, u'utf8_unicode_ci'), nullable=False) 

class Match(Base): 
    __tablename__ = 'match' 
    id = Column(Integer, primary_key=True) 
    guy_id = Column(ForeignKey(u'guy.id'), nullable=False) 
    girl_id = Column(ForeignKey(u'girl.id'), nullable=False) 

    guy = relationship(u'Guy', backref = 'matches') 
    girl = relationship(u'Girl', backref = 'matches') 

class GuyHobbies(Base): 
    __tablename__ = 'guy_hobbies' 
    id = Column(Integer, primary_key=True) 
    guy_id = Column(ForeignKey(u'guy.id'), nullable=False) 
    hobby_id = Column(ForeignKey(u'hobby.id'), nullable=False) 

    guy = relationship(u'Guy', backref = 'hobbies') 
    hobby = relationship(u'Hobby', backref = 'guys') 

class GirlHobbies(Base): 
    __tablename__ = 'girl_hobbies' 
    id = Column(Integer, primary_key=True) 
    girl_id = Column(ForeignKey(u'girl.id'), nullable=False) 
    hobby_id = Column(ForeignKey(u'hobby.id'), nullable=False) 

    girl = relationship(u'Girl', backref = 'hobbies') 
    hobby = relationship(u'Hobby', backref = 'girls') 

Теперь я хочу, чтобы получить соединение между GirlHobby и GuyHobby, который учитывает оба отношения через Хобби и через Матч. I.e., я делаю

matched_hobbies = session.query(GuyHobbies).join(GuyHobbies.guy).\ 
    join(GuyHobbies.hobby).join(Guy.matches).\ 
    join(Match.girl).outerjoin(Girl.hobbies).all() 

Однако сгенерированный запрос пропускает часть, указанную ниже. Как заставить SQLAlchemy добавить это условие?

SELECT guy_hobbies.id AS guy_hobbies_id, guy_hobbies.guy_id AS guy_hobbies_guy_id, 
    guy_hobbies.hobby_id AS guy_hobbies_hobby_id 
FROM guy_hobbies INNER JOIN guy ON guy.id = guy_hobbies.guy_id 
    INNER JOIN hobby ON hobby.id = guy_hobbies.hobby_id 
    INNER JOIN `match` ON guy.id = `match`.guy_id 
    INNER JOIN girl ON girl.id = `match`.girl_id 
    LEFT OUTER JOIN girl_hobbies ON girl.id = girl_hobbies.girl_id 
     #MISSING: AND hobby.id = girl_hobbies.hobby_id 

Дополнение: Я попытался установить прямую связь между GuyHobbies и GirlHobbies использованием

girl_hobbies = relationship('GirlHobbies', 
    primaryjoin ="and_(GuyHobbies.guy_id == Guy.id, 
    Match.guy_id == Guy.id ,Match.girl_id == Girl.id, 
    GirlHobbies.girl_id == Girl.id , 
    GirlHobbies.hobby_id == Hobby.id, 
    GuyHobbies.hobby_id == Hobby.id)") 

пока я получаю довольно ироничное сообщение об ошибке:

Could not locate any simple equality expressions involving locally mapped foreign key columns for primary join condition 'guy_hobbies.guy_id = guy.id AND match.guy_id = guy.id AND match.girl_id = girl.id AND girl_hobbies.girl_id = girl.id AND girl_hobbies.hobby_id = hobby.id AND guy_hobbies.hobby_id = hobby.id' on relationship GuyHobbies.girl_hobbies.

который отображает точно условие соединения Я хочу использовать SQLAlchemy ...

ответ

0

Со всеми кредитами для @inklesspen канала IRC SQLAlchemy - условие соединения должно быть указано непосредственно в соединении, то есть

matched_hobbies = session.query(GuyHobbies).join(GuyHobbies.guy).\ 
    join(GuyHobbies.hobby).join(Guy.matches).\ 
    join(Match.girl).\ 
    outerjoin(GirlHobbies, 
     and_(GirlHobbies.hobby_id == GuyHobbies.hobby_id, 
      GirlHobbies.girl_id == Girl.id)).all() 
Смежные вопросы