2013-06-04 75 views
2

我有一個樹看起來像這樣,通過多態繼承反映:SQLAlchemy的嵌套繼承/多態性關係

 A 
/ | \ 
    B C D 

那偉大工程,如:

class BaseModel(db.Model):  # Table A in diagram 
    __tablename__ = "entities" 

    id = db.Column(db.BigInteger, primary_key=True, nullable=False, server_default=func.nextval('guid_seq')) 
    type_id = db.Column(db.SmallInteger, db.ForeignKey(EntityTypesModel.id)) 

    __mapper_args__ = { 
     'polymorphic_identity':'entity', 
     'polymorphic_on':type_id, 
     'with_polymorphic':'*' 
    } 

class BrandModel(BaseModel): # Table B, C, D in diagram 
    __tablename__ = 'brands' 

    id = db.Column(db.BigInteger, db.ForeignKey(StufffModel.id), primary_key=True, nullable=False) 
    name = db.Column(db.String, nullable=False) 

    __mapper_args__ = { 
     'polymorphic_identity':ET_BRAND, 
    } 

的問題是我需要反思更多類似的東西:

   A 
     / | \ 
      B C D 
       / \ 
       E F 

其中D不僅是A的多形兒童,而且A也是E的多態性親本F.

看起來我必須選擇,D可以是一個多態的孩子,或者它可以是一個父母 - 它不能兩者兼而有之。

我在這裏有什麼選擇嗎?

編輯:

只是爲了配合這一關,我結束了扁平化的樹,以便它看起來像:

 A 
/ | \ \ 
B C E F 

d現在已經沒有了,它提供的功能是在孩子(E & F)。我可能會將常見的部分變成mixin或其他東西。

不幸的,但我不能花更多的時間在這個特定的問題上。

回答

3

你絕對可以做到這一點。下面的代碼使用declarative_base,但顯示了可用的模型設置。 D類是使用類繼承的父類和子類。但是,polymorphic_identity僅存儲在頂層。確保你有所有正確的外鍵和類繼承設置。

*注:如你定義TYPE_ID作爲數字,不過值似乎是字符串*

Base = declarative_base(cls=_BaseMixin) 
Base.query = session.query_property() 

class BaseModel(Base): 
    __tablename__ = 'entities' 
    id = Column(Integer, primary_key=True) 
    #type_id = Column(Integer, nullable=False) 
    type_id = Column(String, nullable=False) 
    __mapper_args__ = { 
     'polymorphic_identity': 'entity', 
     'polymorphic_on':type_id, 
     'with_polymorphic':'*' 
    } 

class ModelB(BaseModel): 
    __tablename__ = 'modelB' 
    __mapper_args__ = {'polymorphic_identity': 'modelB'} 
    id = Column(Integer, ForeignKey('entities.id'), primary_key=True) 
    name = Column(String, nullable=False) 

class ModelC(BaseModel): 
    __tablename__ = 'modelC' 
    __mapper_args__ = {'polymorphic_identity': 'modelC'} 
    id = Column(Integer, ForeignKey('entities.id'), primary_key=True) 
    name = Column(String, nullable=False) 

class ModelD(BaseModel): 
    __tablename__ = 'modelD' 
    __mapper_args__ = {'polymorphic_identity': 'modelD'} 
    id = Column(Integer, ForeignKey('entities.id'), primary_key=True) 
    name = Column(String, nullable=False) 

class ModelE(ModelD): 
    __tablename__ = 'modelE' 
    __mapper_args__ = {'polymorphic_identity': 'modelE'} 
    id = Column(Integer, ForeignKey('entities.id'), ForeignKey('modelD.id'), primary_key=True) 
    name = Column(String, nullable=False) 

class ModelF(ModelD): 
    __tablename__ = 'modelF' 
    __mapper_args__ = {'polymorphic_identity': 'modelF'} 
    id = Column(Integer, ForeignKey('entities.id'), ForeignKey('modelD.id'), primary_key=True) 
    name = Column(String, nullable=False) 
+0

因此,這看起來是捎帶折MODELA鑑別列TYPE_ID的。實際上,模型D E F被另一列區分 - 也許稱它爲type_inner_id。但ModelD必須在type_id列上保持與ModelA相關的多態性。 – amirpc

+0

我相信這是有道理的,並且絕對不會稱它爲小豬支持。太棒了,你找到了一個你可以接受的解決方案。 – van

+0

你現在怎麼能把一個ForeignKey從類「Ricky(Base)」綁定到BaseModel(Base)中的表「實體」?它不斷給我:sqlalchemy.exc.NoReferencedTableError –