SQLAlchemy:在关系表中带有额外列的自引用多对多关系

时间:2019-07-26 06:10:39

标签: python sqlalchemy

我正在尝试使用称为sort_order的额外列创建自引用多对多关系表:

from sqlalchemy import Integer, ForeignKey, String, Column, Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.orderinglist import ordering_list

Base = declarative_base()

class Node2Node(Base):
    __tablename__ = "NodeToNode"
    left_node_id = Column(Integer, ForeignKey("Node.id"), primary_key=True)
    right_node_id = Column(Integer, ForeignKey("Node.id"), primary_key=True)
    sort_order = Column(Integer, nullable=False)


class Node(Base):
    __tablename__ = "Node"
    id = Column(Integer, primary_key=True)
    label = Column(String)

    # Many To Many with Node
    right_nodes = relationship(
        "Node",
        secondary="NodeToNode",
        primaryjoin="Node.id==NodeToNode.c.left_node_id",
        secondaryjoin="Node.id==NodeToNode.c.right_node_id",
        backref="left_nodes",
        order_by="NodeToNode.c.sort_order",
    )

    def __repr__(self):
        return f"<Node: {self.label}>"

运行以下脚本时,出现错误消息NOT NULL constraint failed: NodeToNode.sort_order

from sqlalchemy import create_engine
from sqlalchemy.orm import Session

engine = create_engine("sqlite:///practice.sqlite3")
session = Session(bind=engine)

# Build tables
Base.metadata.drop_all(engine)
Base.metadata.create_all(engine)

# Load in data
nodes = [
    Node(label="A"),
    Node(label="B"),
    Node(label="C"),
    Node(label="D"),
    Node(label="E"),
]

session.add_all(nodes)
session.commit()

nodes[0].right_nodes = [nodes[3], nodes[1], nodes[2]]
nodes[0].left_nodes = [nodes[4]]

session.add_all(nodes)
session.commit()

# Display data
print("Nodes: {}".format(nodes))
print("Node A right nodes: {}".format(nodes[0].right_nodes))
print("Node A left nodes: {}".format(nodes[0].left_nodes))

session.close()

如何根据列表中项目的索引设置此sort_order键?

1 个答案:

答案 0 :(得分:0)

与关联对象使用自引用多对多关系。

请参见https://stackoverflow.com/a/62281276/9387542

上的示例