Skip to main content
extended answer in line with extended question
Source Link
van
  • 77.5k
  • 13
  • 174
  • 179

The code below shows how to configure the relationship:

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,
            )

But few things should be noted:

  • only one end of the relationship is stored, the other is inferred. This might not be what you want, but it is much more simple to manage, and it is enough to set one side only myNode.left = myOtherNode and the other (right) will be set automatically (because of configured backref)
  • if both ends are stored (right and left), then
    • both ends would need to be set in code and one has to ensure they are consistent, which might not be a trivial task
    • the insert of two nodes that are linked would require insert-1, insert-2, update-1 in case your primary key is computed on the database, as it is unknown during the first insert.

UPDATE: Sample code to the UPDATE part of the question (but still using the original class name). One needs only to specify the primaryjoin and uselist=False:

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', primaryjoin = ('NodeClass.left_id == NodeClass.node_id'), use_list=False)
    right = relationship('NodeClass', primaryjoin = ('NodeClass.right_id == NodeClass.node_id'), use_list=False)

The code below shows how to configure the relationship:

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,
            )

But few things should be noted:

  • only one end of the relationship is stored, the other is inferred. This might not be what you want, but it is much more simple to manage, and it is enough to set one side only myNode.left = myOtherNode and the other (right) will be set automatically (because of configured backref)
  • if both ends are stored (right and left), then
    • both ends would need to be set in code and one has to ensure they are consistent, which might not be a trivial task
    • the insert of two nodes that are linked would require insert-1, insert-2, update-1 in case your primary key is computed on the database, as it is unknown during the first insert.

The code below shows how to configure the relationship:

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,
            )

But few things should be noted:

  • only one end of the relationship is stored, the other is inferred. This might not be what you want, but it is much more simple to manage, and it is enough to set one side only myNode.left = myOtherNode and the other (right) will be set automatically (because of configured backref)
  • if both ends are stored (right and left), then
    • both ends would need to be set in code and one has to ensure they are consistent, which might not be a trivial task
    • the insert of two nodes that are linked would require insert-1, insert-2, update-1 in case your primary key is computed on the database, as it is unknown during the first insert.

UPDATE: Sample code to the UPDATE part of the question (but still using the original class name). One needs only to specify the primaryjoin and uselist=False:

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', primaryjoin = ('NodeClass.left_id == NodeClass.node_id'), use_list=False)
    right = relationship('NodeClass', primaryjoin = ('NodeClass.right_id == NodeClass.node_id'), use_list=False)
Source Link
van
  • 77.5k
  • 13
  • 174
  • 179

The code below shows how to configure the relationship:

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,
            )

But few things should be noted:

  • only one end of the relationship is stored, the other is inferred. This might not be what you want, but it is much more simple to manage, and it is enough to set one side only myNode.left = myOtherNode and the other (right) will be set automatically (because of configured backref)
  • if both ends are stored (right and left), then
    • both ends would need to be set in code and one has to ensure they are consistent, which might not be a trivial task
    • the insert of two nodes that are linked would require insert-1, insert-2, update-1 in case your primary key is computed on the database, as it is unknown during the first insert.