SQLAlchemy eager load specific subtype collection

Viewed 685

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!

1 Answers
Related