2012-07-09 44 views
0

我正在查询由第三方维护的专有数据库。数据库有许多表,每个表都有大量的字段。使用反射建模复杂关系的SQLAlchemy

我的问题涉及三个感兴趣的表格,Tree,Site和Meter。

树表描述了简单树结构中的节点。与其他数据一起,它有一个外键引用自己的主键。它还有一个Object_Type字段和一个Object_ID字段。 Site和Meter表中每个都有很多字段。

树节点有一比一的关系要么是一米网站。如果Object_Type字段为1,则Object_ID字段引用Site表中的主键。如果它是2,则它指的是Meter表中的主键。

下面这个例子https://bitbucket.org/sqlalchemy/sqlalchemy/src/408388e5faf4/examples/declarative_reflection/declarative_reflection.py

我使用反射来加载像这样

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

这是很难跟随你的问题,但或许把一个指数[OBJECT_ID,OBJECT_TYPE],因为那将是每个树节点是唯一的。 – AJcodez 2012-07-09 19:08:26

回答

1

树。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 
2

首先注意反射。我发现自己比不依靠反思更好。

  1. 它并不需要一个有效的数据库连接,为您加载/工作与你的代码
  2. 它违反了蟒蛇的指南,明确优于隐式。如果你看看你的代码,你最好是看到的元素(列等),而不是让他们神奇地创建你的视野外。

这意味着更多的代码,但更易于维护。

我提出这个问题的原因至少部分是因为我看不到您的帖子中的架构。

如果您在代码中创建表和类而不是依赖反射,则可以更好地控制映射。

在你想使用多态映射

  1. 创建一个TreeNode类如上这种情况下。
  2. 创建SiteNode和MeterNode作为子类

你的代码,然后将包括类似:

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) 

希望这有助于。