2012-07-09 52 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) 

希望這有助於。