我目前使用单表继承策略映射类层次结构(我不可能使用join)。此层次结构可能如下所示:
class Parent(Base):
__tablename__ = 'mytable'
__mapper_args__ = {
'polymorphic_on' : type,
'polymorphic_identity' : 'parent'
}
id = Column(Integer, primary_key = True)
type = Column(String(32), nullable = False)
class Child1(Parent):
__mapper_args__ = { 'polymorphic_identity' : 'child1' }
property1 = Column(Integer)
class Child2(Parent):
__mapper_args__ = { 'polymorphic_identity' : 'child2' }
property1 = Column(Integer)
class Child3(Parent):
__mapper_args__ = { 'polymorphic_identity' : 'child3' }
other_property = Column(Integer)
问题是,我想在property1
和Child1
上都有Child2
,但Child3
却没有。上面的当前代码导致错误:
sqlalchemy.exc.ArgumentError: Column 'property1' on class <class
'__main__.Child2'> conflicts with existing column 'mytable.property1'
我当然可以在继承层次结构中添加另一个层Child1
和Child2
派生自并包含property1
列,但Child1
和Child2
虽然我想为两个类重用相同的数据库列,但它们之间几乎没有关系。
我已经尝试将property1 = Child1.property1
添加到Child2
但是没有用(实例值没有存储在Child2
的数据库中)
有人能指出如何重用已由另一个子类定义的列吗?
答案 0 :(得分:12)
直接适应Resolving Column Conflicts的文档:
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base, declared_attr
Base = declarative_base()
class Parent(Base):
__tablename__ = 'mytable'
id = Column(Integer, primary_key = True)
type = Column(String(32), nullable = False)
__mapper_args__ = {
'polymorphic_on' : type,
'polymorphic_identity' : 'parent'
}
class Child1(Parent):
__mapper_args__ = { 'polymorphic_identity' : 'child1' }
@declared_attr
def property1(cls):
return Parent.__table__.c.get('property1', Column(Integer))
class Child2(Parent):
__mapper_args__ = { 'polymorphic_identity' : 'child2' }
@declared_attr
def property1(cls):
return Parent.__table__.c.get('property1', Column(Integer))
class Child3(Parent):
__mapper_args__ = { 'polymorphic_identity' : 'child3' }
other_property = Column(Integer)
e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)
s = Session(e)
s.add_all([Child1(property1=1), Child2(property1=2), Child3(other_property=3)])
s.commit()
for p in s.query(Parent):
if isinstance(p, (Child1, Child2)):
print p.property1
elif isinstance(p, Child3):
print p.other_property