Start here
The safe first move
Use chained joinedload(...) calls with mapped attributes for clear paths. Stop for aliases, contains_eager, and duplicate join interactions.
Stop before automation when: contains_eager usage. Aliased classes in the same query.
Target shape
query = session.query(User).options(
joinedload(User.orders).joinedload(Order.items)
)