使用SQLAlchemy具有多个自引用外键

时间:2012-05-14 20:46:06

标签: python foreign-keys sqlalchemy relational-database

如果我在关系数据库中有类似双链表的内容,例如:

,该怎么办?
node_id    left_id    right_id

1          null       2
2          1          3
3          2          null

然后我有一些SQLAlchemy代码,如下所示:

class NodeClass(Base):
    __tablename__ = 'nodes_table'
    node_id = Column(Integer, primary_key=True)
    left_id = Column(Integer, ForeignKey('nodes_table.node_id'))
    right_id = Column(Integer, ForeignKey('nodes_table.node_id'))
    left = relationship('NodeClass') # Wrong
    right = relationship('NodeClass') # Wrong

如果我有node_id 2,并且我调用NodeClass.left我想收到node_id 1作为回报。如何配置SQLAlchemy关系以这种方式运行?

更新:

我将举一个例子。考虑一个人的表,每个人都有一个母亲和一个父亲。

person_id    mother_id    father_id

1            null         null
2            null         null
3            1            2

SQLAlchemy代码:

class PersonClass(Base):
    __tablename__ = 'persons_table'
    person_id = Column(Integer, primary_key=True)
    mother_id = Column(Integer, ForeignKey('persons_table.person_id'))
    father_id = Column(Integer, ForeignKey('persons_table.person_id'))
    mother = relation('PersonClass') # Wrong
    father = relation('PersonClass') # Wrong

1 个答案:

答案 0 :(得分:4)

以下代码显示了如何配置关系:

class NodeClass(Base):
    __tablename__ = 'nodes_table'
    node_id = Column(Integer, primary_key=True)

    left_id = Column(Integer, ForeignKey('nodes_table.node_id'))
    left = relationship('NodeClass', remote_side=[node_id],
            primaryjoin=('NodeClass.left_id==NodeClass.node_id'),
            backref=backref("right", uselist=False),
            #lazy="joined", join_depth=9,
            )

但很少有事情要注意:

  • 只存储关系的一端,另一端是推断的。这可能不是您想要的,但管理起来要简单得多,仅设置一侧myNode.left = myOtherNode就足够了,另一侧(right)将自动设置(因为已配置{ {1}})
  • 如果两端都存储(backrefright),那么
    • 两端都需要在代码中设置,并且必须确保它们是一致的,这可能不是一项微不足道的任务。
    • 如果您的主键是在数据库上计算的,那么链接的两个节点的插入将需要left,因为在第一个insert-1, insert-2, update-1期间它是未知的。

更新:问题的UPDATE部分的示例代码(但仍使用原始类名)。只需要指定insertprimaryjoin

uselist=False