Reputation: 1668
I have a tree that looks like this, reflected via polymorphic inheritance:
A
/ | \
B C D
That works great, like:
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,
}
The problem is I need to reflect something more like this:
A
/ | \
B C D
/ \
E F
Where D is not only a polymorphic child of A but also the polymorphic parents of E & F.
It seems like I have to choose, D can either be a polymorphic child or it can be a parent - it can't be both.
Do I have any options here?
EDIT:
Just to tie this off, I ended up flattening the tree so it looks like:
A
/ | \ \
B C E F
D is now gone and the functionality it provided is in the children (E & F). I'll probably make the common parts a mixin or something.
Unfortunate but I couldn't spend more time on this particular issue.
Upvotes: 4
Views: 2885
Reputation: 76952
You definitely can do this. The code below is using the declarative_base
, but shows the model setup which works. D
class is both a parent and a child using class inheritance. However, the polymorphic_identity
is stored only on the top level. Make sure you have all proper foreign keys and class inheritances set up.
*Note: you example defines type_id as Numeric, however the values seem to be Strings.*
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)
Upvotes: 5