我正在查询由第三方维护的专有数据库。数据库有许多表,每个表都有大量的字段。
我的问题涉及三个感兴趣的表格,树,网站和仪表。
树表描述了简单树结构中的节点。与其他数据一起,它有一个引用其自己的主键的外键。它还有一个Object_Type字段和一个Object_ID字段。 Site和Meter表各有许多字段。
树节点具有一对一的关系, 是一个米或一个站点。如果Object_Type字段为1,则Object_ID字段引用Site表中的主键。如果是2那么它指的是Meter表中的主键。
我正在使用反射来加载像这样的表结构
Base = declarative_base(cls=DeclarativeReflectedBase)
class Meter(Base):
__tablename__ = 'Meter'
class Site(Base):
__tablename__ = 'Site'
class Tree(Base):
__tablename__ = 'Tree'
Parent_Node_ID = Column(Integer, ForeignKey('Tree.Node_ID'))
Node_ID = Column(Integer, primary_key=True)
children = relationship("Tree", backref=backref('parent', remote_side=[Node_ID]))
Base.prepare(engine)
我已经包含了自我指涉关系并且完美无缺。如何使用Object_ID作为外键添加两个关系,并对Object_Type字段进行适当的检查?
答案 0 :(得分:2)
首先注意反思。我发现自己好好不依赖于反思。
这意味着更多代码,但更易于维护。
我建议的原因至少部分是我在帖子中看不到架构。
如果您在代码中创建表和类而不是依赖于反射,那么您可以更好地控制映射。
在这种情况下,您希望使用多态映射
您的代码将包含以下内容:
mapper(TreeNode,tree_table,polymorphic_on=tree_table.c.object_type)
mapper(SiteNode, site_table,inherits=TreeNode,
inherit_condition=site_table.c.node_id==tree_table.c.node_id,
polymorphic_identity=1)
希望这有帮助。
答案 1 :(得分:1)
for tree.object_id是一个可以引用Site或Meter的外键,你可以让Site和Meter从公共基表下降,即连接表继承,或者映射到相同的表,即单表继承,或者有人说将Tree映射到两个不同的表以及公共基表。最后一个建议很好地认为TreeNode已经有一个“类型”字段。
最简单的替代方法是直接在TreeNode上使用两个外键 - site_id和meter_id,以及两个关系,“meter”和“site”;然后使用Python @property返回一个或另一个:
class TreeNode(Base):
# ...
@property
def object(self):
return self.meter or self.site