如何使用 SQLAlchemy 在 SQLite 中级联删除?



我一直在阅读SQLAlchemy文档中有关级联删除的各种示例,但我尝试的似乎都不起作用。下面是一些改编自该文档的示例代码,但使用 back_populates 而不是 backref,因为我知道 backref 正在被弃用。

在下面的">主要"部分中,我希望删除"包含"项目的顺序也会删除项目,但这不会发生。显然我不明白如何配置这些表......这是什么?

# third party imports
from sqlalchemy import Column, ForeignKey, Integer, String, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker
from sqlalchemy_utils import create_database, database_exists
Base = declarative_base()

class Order(Base):
__tablename__ = "business_order"
id = Column(Integer, primary_key=True)
name = Column(String(32))
items = relationship(
"Item", back_populates="order", cascade="all, delete, delete-orphan"
)

class Item(Base):
__tablename__ = "business_item"
id = Column(Integer, primary_key=True)
name = Column(String(32))
order_id = Column(Integer, ForeignKey("business_order.id"))
order = relationship("Order", back_populates="items")

def get_session(url="sqlite:///:memory:", create_db=True):
"""Get a SQLAlchemy Session instance for input database URL.
:param url:
SQLAlchemy URL for database, described here:
http://docs.sqlalchemy.org/en/latest/core/engines.html#database-urls.
:param create_db:
Boolean indicating whether to create database from scratch.
:returns:
Sqlalchemy Session instance.
"""
# Create a sqlite in-memory database engine
if not database_exists(url):
if create_db:
create_database(url)
else:
msg = (
"Database does not exist, will not create without "
"create_db turned on."
)
print(msg)
return None
connect_args = {}
engine = create_engine(url, echo=False, connect_args=connect_args)
Base.metadata.create_all(engine)
# create a session object that we can use to insert and
# extract information from the database
Session = sessionmaker(bind=engine, autoflush=False)
session = Session()
return session

if __name__ == "__main__":
sqlite_url = "sqlite:///test_sqlite.db"
session = get_session(sqlite_url)
order = Order(name="order1")
session.add(order)
item = Item(order_id=order.id, name="item1")
session.add(item)
session.commit()
session.delete(order)  # should delete items too, right?
session.commit()
orders = session.query(Order).all()
print(len(orders))  # this returns 0 as expected
items = session.query(Item).all()
print(len(items))  # this returns 1, why?

Order有一个(隐式的)自动增量PK。当你这样做时

order = Order(name="order1")
session.add(order)

order.idNone.因此,当您这样做时

item = Item(order_id=order.id, name="item1")

item.order_id也会None,所以item实际上与order无关。因此,删除不会级联。

order直到调用.flush()(或.commit())才得到它的id。所以你可以做

order = Order(name="order1")
session.add(order)
session.flush()  # !
item = Item(order_id=order.id, name="item1")
session.add(item)
session.commit()

或做

order = Order(name="order1", items=[Item(name="item1")])
session.add(order)
session.commit()
session.delete(order)  # should delete items too, right?
session.commit()
orders = session.query(Order).all()
print(len(orders))  # this returns 0 as expected
items = session.query(Item).all()
print(len(items))  # this also returns 0 as expected

最新更新