假设我有一个数据库结构,其中包含如下表所示的三个表:
class Character(Base):
__tablename__="characters"
id = Column(Integer, primary_key=True)
name = Column(String)
player = Column(String)
inventory = relation(Inventory)
class Item(Base):
__tablename__="items"
id = Column(Integer, primary_key=True)
name = Column(String)
class Inventory(Base):
__tablename__="inventory"
id = Column(Integer, primary_key=True)
char_id = Column(Integer, ForeignKey("characters.id"))
item_id = Column(Integer, ForeignKey("characters.id"))
quantity = Column(Integer)
item = relation(Item)
关联的方式定义如下:
class Character(base):
inventory = relationship("Inventory",
cascade="delete-orphan",
backref="character")
我的问题是,当从 Character.inventory 中删除 Inventory 对象时,在提交会话之前不会更新该对象。例如,如果我这样做:
>>> torch_inv = character.inventory[0] # Inventory object referred to a torch
>>> torch_inv.item, torch_inv.quantity
(<Item object, torch>, 3)
>>> session.delete(torch_inv)
>>> character.inventory[0]
<Inventory object, torch>
可以看到,即使我已经删除了 Inventory 对象,但它仍然存在于 Character.inventory 列表中。
我已经注意到有 “级联” 关系选项,但不知道如何在这种情况下让它起作用。
2. 解决方案
Session.delete() 方法只是将一个实例标记为 “要删除” ,因此在将更改刷新到数据库之前,你的关系不会更改,而与级联规则无关。另一方面,你可以简单地从 Character.inventory 集合中删除 Inventory 实例,然后使用“delete-orphan” 级联规则将删除的 Inventory 实例标记为要删除。
以下是如何使用级联“delete-orphan” 选项来解决此问题的示例代码:
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Character(Base):
__tablename__="characters"
id = Column(Integer, primary_key=True)
name = Column(String)
player = Column(String)
inventory = relationship("Inventory",
cascade="delete-orphan",
backref="character")
class Item(Base):
__tablename__="items"
id = Column(Integer, primary_key=True)
name = Column(String)
class Inventory(Base):
__tablename__="inventory"
id = Column(Integer, primary_key=True)
char_id = Column(Integer, ForeignKey("characters.id"))
item_id = Column(Integer, ForeignKey("characters.id"))
quantity = Column(Integer)
item = relationship(Item)
# 创建数据库引擎
engine = create_engine("sqlite:///mydb.db")
# 创建所有表
Base.metadata.create_all(engine)
# 创建一个会话
session = Session(engine)
# 创建一个角色
character = Character(name="John Doe", player="Jane Doe")
# 创建一个库存项
torch = Item(name="Torch")
# 创建一个库存
inventory = Inventory(item=torch, quantity=3)
# 将库存添加到角色
character.inventory.append(inventory)
# 将角色添加到会话
session.add(character)
# 提交会话
session.commit()
# 检查库存
print(character.inventory)
# 从库存中删除一个库存项
session.delete(character.inventory[0])
# 提交会话
session.commit()
# 检查库存
print(character.inventory)
输出:
[<Inventory object, torch, 3>]
[]
如你所见,在删除库存项后,该项不再存在于角色的库存列表中。