I have this (simplified) user / group model in one of my projects:
import sqlalchemy
import sqlalchemy.ext.declarative
import sqlalchemy.orm
import sqlalchemy.schema
Base = sqlalchemy.ext.declarative.declarative_base()
class Party(Base):
__tablename__ = 'Party'
type = sqlalchemy.Column(
sqlalchemy.String(1),
nullable=False,
)
name = sqlalchemy.Column(
sqlalchemy.String(255),
primary_key=True,
)
__mapper_args__ = {
'polymorphic_identity': 'S',
'polymorphic_on': type,
}
class User(Party):
__tablename__ = 'User'
name = sqlalchemy.Column(
sqlalchemy.String(255),
sqlalchemy.schema.ForeignKey(Party.name),
primary_key=True,
)
__mapper_args__ = {
'polymorphic_identity': 'U',
}
class Group(Party):
__tablename__ = 'User'
name = sqlalchemy.Column(
sqlalchemy.String(255),
sqlalchemy.schema.ForeignKey(Party.name),
primary_key=True,
)
__mapper_args__ = {
'polymorphic_identity': 'G',
}
class UserGroup(Base):
__tablename__ = 'UserGroup'
user_name = sqlalchemy.Column(
sqlalchemy.String(255),
sqlalchemy.schema.ForeignKey(User.name),
primary_key=True,
)
group_name = sqlalchemy.Column(
sqlalchemy.String(255),
sqlalchemy.schema.ForeignKey(Group.name),
primary_key=True,
)
user = sqlalchemy.orm.relationship(User, backref='user_groups')
I encounter a problem when trying eager load the user_groups property of User in a polymorphic query:
party_poly = sqlalchemy.orm.with_polymorphic(Party, [User, Group])
results = session.query(party_poly) \
.options(sqlalchemy.orm.subqueryload(User.user_groups)) \
.all()
The error given is:
Can't find property 'user_groups' on any entity specified in this Query. Note the full path from root (Mapper|Party|Party) to target entity must be specified.
Through trial and error I got this query to work by changing
party_poly = sqlalchemy.orm.with_polymorphic(Party, [User, Group])
to
party_poly = sqlalchemy.orm.with_polymorphic(Party, [User, Group],
_use_mapper_path=True)
So the question is; is it safe to rely on the undocumented, private argument _use_mapper_path argument? Does anyone know what it does?
Is there a better way to do what I'm trying to do? If there is I'd like to hear it!