使用二级表时SQLAlchemy的ON DELETE SET NULL

3 投票
1 回答
3745 浏览
提问于 2025-04-17 19:30

我遇到了一个基本的使用场景——我有两个表,分别是节点表(Nodes)和网络表(Networks),它们通过一个第三个表(IPAddr)相互关联,这个第三个表就像是个中介表:

class Node(Base, BasicValidator):
    __tablename__ = 'nodes'
    id = Column(Integer, primary_key=True)

class IPAddr(Base):
    __tablename__ = 'ip_addrs'
    id = Column(Integer, primary_key=True)
    network = Column(Integer, ForeignKey('networks.id'))
    node = Column(Integer, ForeignKey('nodes.id'))
    ip_addr = Column(String(25), nullable=False)

class Network(Base, BasicValidator):
    __tablename__ = 'networks'
    id = Column(Integer, primary_key=True)
    nodes = relationship(
        "Node",
        secondary=IPAddr.__table__,
        backref="networks")

现在,当我从数据库中删除网络对象时,出现了以下错误:

详细信息:键 (id)=(9) 仍然在表 "ip_addrs" 中被引用。 'DELETE FROM networks WHERE networks.id = %(id)s' ({'id': 6}, {'id': 7}, {'id': 8}, {'id': 9}, {'id': 10})

我只需要做的就是 在删除网络和IPAddr的同时保留节点

我尝试过这个:http://docs.sqlalchemy.org/en/rel_0_7/orm/relationships.html#association-object,但没有帮助,即使使用了AssociationProxy,这次虽然一切正常,但如果我这样做然后删除节点,Network.nodes 返回的却是[None]

class Node(Base, BasicValidator):
    __tablename__ = 'nodes'
    id = Column(Integer, primary_key=True)

class IPAddr(Base):
    __tablename__ = 'ip_addrs'
    id = Column(Integer, primary_key=True)
    network = Column(Integer, ForeignKey('networks.id'))
    node = Column(Integer, ForeignKey('nodes.id'))
    nodes = relationship("Node", backref="networks_assocs")
    ip_addr = Column(String(25), nullable=False)

class Network(Base, BasicValidator):
    __tablename__ = 'networks'
    id = Column(Integer, primary_key=True)
    nd = relationship("IPAddr", backref="networks")
    nodes = association_proxy('nd', 'nodes')

有人能帮忙吗,正确的做法是什么?

1 个回答

0

如果你的数据库支持的话,你需要使用类似于“ON DELETE CASCADE”的功能。

想了解更多,可以查看这里: http://docs.sqlalchemy.org/en/latest/orm/session.html#unitofwork-cascades

撰写回答