2011-07-21 41 views
7

基本上,我有這個模型,我在單個表中映射了一個「BaseNode」類和兩個子類。關鍵是我需要其中一個子類,以便與其他子類具有一對多的關係。 因此,在排序中,它是與不同類(子類)的另一行的關係,但在同一個表中。 您認爲我可以使用聲明性語法來編寫它嗎?SQLAlchemy在單個表繼承上的一對多關係 - 聲明式

注意:由於我模型中的其他關係,如果可能的話,我確實需要堅持單表繼承。

class BaseNode(DBBase): 
    __tablename__ = 'base_node' 
    id = Column(Integer, primary_key=True) 
    discriminator = Column('type', String(50)) 
    __mapper_args__ = {'polymorphic_on': discriminator} 

class NodeTypeA(BaseNode): 
    __mapper_args__ = {'polymorphic_identity': 'NodeTypeA'} 
    typeB_children = relationship('NodeTypeB', backref='parent_node') 


class NodeTypeB(BaseNode): 
    __mapper_args__ = {'polymorphic_identity': 'NodeTypeB'} 
    parent_id = Column(Integer, ForeignKey('base_node.id')) 

使用此代碼會拋出:

sqlalchemy.exc.ArgumentError: NodeTypeA.typeB_children and back-reference NodeTypeB.parent_node are both of the same direction . Did you mean to set remote_side on the many-to-one side ?

任何意見或建議?

回答

8

我早些時候正在努力解決這個問題。我能得到這個自我指涉的關係的工作:

class Employee(Base): 
    __tablename__ = 'employee' 
    id = Column(Integer, primary_key=True) 
    name = Column(String(64), nullable=False) 
Employee.manager_id = Column(Integer, ForeignKey(Employee.id)) 
Employee.manager = relationship(Employee, backref='subordinates', 
    remote_side=Employee.id) 

注意,managermanager_id是「猴子打補丁」,因爲你不能在一個類定義內作出自我引用。

所以在你的榜樣,我想這:

class NodeTypeA(BaseNode): 
    __mapper_args__ = {'polymorphic_identity': 'NodeTypeA'} 
    typeB_children = relationship('NodeTypeB', backref='parent_node', 
     remote_side='NodeTypeB.parent_id') 

編輯:基本上你的錯誤是告訴你的是,關係及其backref都是相同的。因此,無論SA應用什麼規則來確定表級關係是什麼,他們都不會與您提供的信息一起工作。

我瞭解到,只要在聲明類中聲明mycolumn=relationship(OtherTable)就會導致mycolumn成爲一個列表,假設SA可以檢測到明確的關係。所以如果你真的想要一個對象有一個鏈接到其父,而不是它的子女,你可以在子表中定義parent=relationship(OtherTable, backref='children', remote_side=OtherTable.id)。這定義了父子關係的兩個方向。

+0

感謝您的快速回復! 我試過了,但我仍然得到相同的錯誤。 我應該如何更改NodeTypeB類? 在您的代碼中,您定義了Employee.manager_id和Employee.manager類定義之外。但是在你對我的代碼的建議中,你沒有。 對不起,我覺得我不清楚。 此致敬禮。 –

+0

SQLAlchemy文檔表示可以提供獲得eval'd的字符串,以便您可以解決自引用語法錯誤。但我從來沒有嘗試過。 – wberry

+0

在NodeTypeB中,您的外鍵是asset_base。我想這是一個錯字,或者在發佈之前忘了更改名稱。我認爲如果你將ForeignKey('asset_base.id')更改爲ForeignKey(NodeTypeA.id),那麼它將接近我的工作示例。 – wberry