如何在SqlAlchemy中级联删除多个表?

2 投票
2 回答
1118 浏览
提问于 2025-04-16 03:55

我有一个表格,这个表格里有几个相关的表格,我想要在删除时让它们一起删除。但是我遇到了一些问题,删除的范围太广了。下面的代码可以帮助说明这个问题。

class Map(Base):
    ....
    #One to many relationship between the Map and Tile.
    #Each Map is made up of many tiles
    tiles = relationship('Tile', lazy='joined', backref='map',
                          cascade="all, delete")

class Tile(Base):
    ....
    #Reference to Map class.
    map_id = Column(Integer,
                ForeignKey('maps.id'),
                nullable=False)

    #Reference to graphics for this tile
    #This is a many to one relationship, each Graphic is used by many Tiles
    graphics_id = Column(Integer,
                     ForeignKey("graphics.id"),
                     nullable=False)

    graphics = relationship("Graphic", uselist=False)

class Graphic(Base):
    ....
    #Nothing special here

问题是,当我删除地图类的时候,地图图形也被删除了,这不是我想要的。我猜这和级联删除有关。

我该怎么做才能让删除地图类的时候只删除瓷砖,而不删除图形呢?

2 个回答

0

你的代码(除非有些细节被省略)应该能按你预期的那样工作:
图形不应该被删除。从relationship可以看出,默认的cascade参数是save-update, merge,这意味着如果你删除一个Map,不应该触发delete

为了测试,请创建一个例程,生成一个Map、一个Tile和一个Graphic;然后删除这个Map,检查一下Graphic是否被删除——我不认为会发生这种情况。如果这个推测是正确的,那么你的Graphic对象一定是因为其他某个relationship被删除的。

我提到的是SA版本0.64,但我相信在早期版本中,默认配置也没有什么不同。

0

我通过把

graphics = relationship("Graphic", uselist=False)

改成

graphics = relationship("Graphic", uselist=False, lazy='joined',
        backref=backref('tiles', cascade="all, delete, delete-orphan"))

让它正常运行了。

我不确定这是不是最完美的答案,但它确实有效。

撰写回答