我在我的一个项目中有这个(简化的)用户/组模型:
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
参数是否安全?有谁知道它的作用?
有没有更好的方法来做我想做的事情?如果有,我想听听它!
答案 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' )
这避免了在类定义中没有类的一些常用属性的混淆,并且导致显着更少的映射器错误,因为它迫使您指定存在关系。