7

我目前使用单表继承策略映射类层次结构(我不可能使用joined)。此层次结构可能如下所示:

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在两者上都有一个Child1Child2不是在Child3. 上面的当前代码导致错误:

sqlalchemy.exc.ArgumentError: Column 'property1' on class <class
'__main__.Child2'>  conflicts with existing column 'mytable.property1'

我当然可以在继承层次结构中添加另一个层,该层派生自并包含该Child1列,但彼此之间几乎没有关联,尽管我想为两个类重用相同的数据库列。Child2property1Child1Child2

我已经尝试添加property1 = Child1.property1Child2但没有奏效(实例值未存储在数据库中Child2

谁能指出如何重用已经由另一个子类定义的列?

4

1 回答 1

15

直接从解决列冲突中的文档改编:

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
于 2013-06-17T05:33:16.703 回答