简体   繁体   中英

sqlalchemy multiple join conditions through association proxy

I have three structures with data at each possible relationship point between them (call them a, b, and c). I declare these relations (with the associated tables) like so...

class A(Base):
    __tablename__ = 'a'

    id            = Column( types.Integer(), primary_key = True )

    abs           = orm.relation( 'AB' )
    acs           = orm.relation( 'AC' )

# similarly for b and c

class AB(Base):
    __tablename__ = 'ab'

    id            = Column( types.Integer(), primary_key = True )
    a_id          = Column( types.Integer(), ForeignKey( 'a.id' ) )
    b_id          = Column( types.Integer(), ForeignKey( 'b.id' ) )

    a             = orm.relation( 'A' )
    b             = orm.relation( 'B' )

    abcs          = orm.relation( 'ABC' )
    acs           = association_proxy( 'abcs', 'ac' )

# similarly for ac

class ABC(Base):
    __tablename__ = 'abc'

    id            = Column( types.Integer(), primary_key = True )
    ab_id         = Column( types.Integer(), ForeignKey( 'ab.id' ) )
    ac_id         = Column( types.Integer(), ForeignKey( 'ac.id' ) )

    ab            = orm.relation( 'AB' )
    ac            = orm.relation( 'AC' )

Now the following code fails:

abs = db.session.query( AB ).join( A ).join( AC ).join( C ).join( B ).join( ABC, and_(
    ABC.ab_id == AB.id,
    ABC.ac_id == AC.id
) ).all()

The above yields the following error:

ArgumentError: Can't determine join between 'Join object on Join object on Join object on Join object on Join object on ab(163066988) and a(162822028)(175636236) and ac(162854924)(2936229868) and c(161105164)(2936272780)' and 'abc'; tables have more than one foreign key constraint relationship between them. Please specify the 'onclause' of this join explicitly.

It seems that SQLAlchemy doesn't support this kind of joining automatically or via specifying multiple join conditions. The correct way to do this is to use one of the automatic joins (eg AB.abcs ) and specify the other condition as a filter.

abs = db.session.query( AB ).join( AB.a ).join( A.acs ).join( AC.c )\
    .join( AB.b ).join( AB.abcs ).filter( ABC.ac_id = AC.id ).all()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM