How to add 2 conditions to the ON clause when you join 2 tables.
I have 3 three tables in hierarchy each with the deleted flag. I have to join all these table in a single query and filter based on deleted flag also. Currently the conditions gets added to the where clause of the query, which does not filter the deleted records.
It needs to be added to the ON clause. Please suggest.

My current query is as follows:

result = session.query(Host).filter(and_(Host.id.in_(ids), Host.deleted == False)).\
    join(Switch).filter(Switch.deleted == False).\
    join(Port).filter(Port.deleted == False).\
    options(joinedload('switches')).\
    options(joinedload('ports')).\
    all()

Thankyou

Try contains_eager instead of joinedload. What is probably happening is that you have 4 joins the two you defined with join and then then the two from the options(joinedload(…))

Modifying your code, should give this:

from sqlalchemy import and_

result = (session.query(Host).filter(and_(Host.id.in_(ids), Host.deleted == False)).
    join(Switch, and_(Switch.host_id==Host.id, Switch.deleted == False)).
    join(Port, and_(Port.switch_id==Switch.id, Port.deleted == False)).
    options(contains_eager('switches')).
    options(contains_eager('ports')).
    all()
)

The and_() conjunction is also available using the Python & operator (though note that compound expressions need to be parenthesized in order to function with Python operator precedence behavior):
There are also | for or_() and ~ for not_()

So using & operator your code will look like this:

result = session.query(Host).filter(Host.id.in_(ids) & (Host.deleted == False)).
    join(Switch, (Switch.host_id==Host.id) & (Switch.deleted == False)).
    join(Port, (Port.switch_id==Switch.id) & (Port.deleted == False)).
    options(contains_eager('switches')).
    options(contains_eager('ports')).
    all()
)

You can specify the ON clause explicitely in the Query.join call using onclause parameter. Then you query should look like below (not tested):

from sqlalchemy import and_

result = (session.query(Host).filter(and_(Host.id.in_(ids), Host.deleted == False)).
    join(Switch, and_(Switch.host_id==Host.id, Switch.deleted == False)).
    join(Port, and_(Port.switch_id==Switch.id, Port.deleted == False)).
    options(joinedload('switches')).
    options(joinedload('ports')).
    all()
)