SQLAlchemy渴望加载特定的子类型集合

时间:2013-12-10 22:34:47

标签: python sqlalchemy

我在我的一个项目中有这个(简化的)用户/组模型:

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')

在多态查询中尝试急切加载user_groups User属性时遇到问题:

party_poly = sqlalchemy.orm.with_polymorphic(Party, [User, Group])
results = session.query(party_poly) \
    .options(sqlalchemy.orm.subqueryload(User.user_groups)) \
    .all()

给出的错误是:

  

在此Query中指定的任何实体上找不到属性“user_groups”。   请注意,必须指定从根(Mapper | Party | Party)到目标实体的完整路径。

通过反复试验,我通过更改

来解决此问题
party_poly = sqlalchemy.orm.with_polymorphic(Party, [User, Group])

party_poly = sqlalchemy.orm.with_polymorphic(Party, [User, Group],
                                             _use_mapper_path=True)

所以问题是;依赖未记录的私有参数_use_mapper_path参数是否安全?有谁知道它的作用?

有没有更好的方法来做我想做的事情?如果有,我想听听它!

1 个答案:

答案 0 :(得分:0)

_use_mapper_path会导致生成的AliasedClass生成整个映射器。没有它,AliasedClass将只生成自己的类定义(因此不包含user_groups的backref。)

我更喜欢明确地包含backrefs。例如:

class A (db.Model):

    __tablename__ = 'a'

    something = db.Column( db.BigInteger( unsigned=True ), primary_key=True )

    b         = db.relationship( 'B', use_list=False )

class B (db.Model):

    __tablename__ = 'b'

    a_id      = db.Column( db.BigInteger( unsigned=True ), db.ForeignKey( 'a.id' ), primary_key=True )

    a         = db.relationship( 'A' )

这避免了在类定义中没有类的一些常用属性的混淆,并且导致显着更少的映射器错误,因为它迫使您指定存在关系。