Python中Sqlalchemy的级联删除配置方法
class BaseModel(Model):
id = Column(Integer, primary_key=True)
created_at = Column(DateTime(True), default=func.now(), nullable=False)
updated_at = Column(DateTime(True), default=func.now(), onupdate=func.now(), nullable=False)
@classmethod
def create(cls, **kw):
session = db.session
if 'id' in kw:
obj = session.query(cls).get(kw['id'])
if obj:
return obj
obj = cls(**kw)
session.add(obj)
session.commit()
return obj
def to_dict(self):
columns = self.__table__.columns.keys()
return {key: getattr(self, key) for key in columns}
app = Flask(name)
app.config[‘SQLALCHEMY_DATABASE_URI’] = ‘sqlite:///…/cnblogblog.db’
db = SQLAlchemy(app, model_class=BaseModel)
######################################################################################################
class Parent(db.Model):
tablename = ‘parent’
id = Column(Integer, primary_key=True)
name = Column(String(20))
class Child(db.Model):
tablename = ‘child’
id = Column(Integer, primary_key=True)
name = Column(String(20))
parent_id = Column(Integer, ForeignKey('parent.id'))
parent = relationship("Parent", backref=backref("child"))
### 只删除父级,子不影响
# 1. parent_id = Column(Integer, ForeignKey('parent.id', ondelete="CASCADE"))
# parent = relationship("Parent", backref=backref("child", passive_deletes=True))
### 子级跟随删除
# 2. parent = relationship("Parent", backref = backref("child", cascade="all, delete-orphan"))
# 3. parent = relationship("Parent", backref = backref("child", cascade="all,delete"))
## 父级删除,子级不删除,外键更新为 null
# 4. parent = relationship("Parent", backref = backref("child"))
if name == ‘main’:
db.create_all()
Parent.create(name=‘ZhangTian’)
Parent.create(name=‘LiTian’)
Child.create(name=‘ZhangDi’, parent_id=1)
Child.create(name=‘LiDi’, parent_id=2)
parent = db.session.query(Parent).first()
db.session.delete(parent)
db.session.commit()
```
Python中Sqlalchemy的级联删除配置方法
在SQLAlchemy里配置级联删除,主要是在定义relationship时设置cascade参数。最常用的选项是"all, delete-orphan",它能确保父对象被删除时,相关联的子对象也被删除。
下面是一个完整的例子,假设我们有两个模型:Parent和Child,它们是一对多的关系。
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.orm import declarative_base, relationship, sessionmaker
Base = declarative_base()
class Parent(Base):
__tablename__ = 'parents'
id = Column(Integer, primary_key=True)
name = Column(String)
# 关键在这里:cascade='all, delete-orphan'
children = relationship('Child', back_populates='parent', cascade='all, delete-orphan')
class Child(Base):
__tablename__ = 'children'
id = Column(Integer, primary_key=True)
name = Column(String)
parent_id = Column(Integer, ForeignKey('parents.id'))
parent = relationship('Parent', back_populates='children')
# 创建数据库和会话
engine = create_engine('sqlite:///cascade_example.db')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
# 创建数据
parent = Parent(name='John')
child1 = Child(name='Child1')
child2 = Child(name='Child2')
parent.children.extend([child1, child2])
session.add(parent)
session.commit()
# 测试删除:删除parent,其children也会被自动删除
parent_in_db = session.query(Parent).filter_by(name='John').first()
session.delete(parent_in_db)
session.commit()
# 验证:此时查询Child表应该为空
remaining_children = session.query(Child).all()
print(f"Remaining children after parent deletion: {remaining_children}") # 输出: []
session.close()
代码解释:
- 模型定义:
Parent模型中的children关系字段是关键。cascade='all, delete-orphan'意味着:all:包含了所有级联操作(如save-update,merge,delete等)。delete-orphan:当子对象从父对象的集合中移除(即成为“孤儿”)时,也会被删除。这在配置级联删除时通常是必需的组合。
- 外键:
Child表中的parent_id是外键,指向parents.id,这是关系的基础。 - 测试:代码创建了一个父对象和两个子对象,然后删除父对象。提交后查询子表,结果为空,证明级联删除生效。
其他常用cascade选项:
"save-update":默认包含,允许通过父对象添加子对象。"delete":仅删除级联,但不处理“孤儿”。- 你可以组合多个选项,例如
cascade="save-update, merge, delete"。
一句话总结:在父模型的relationship里加上cascade='all, delete-orphan'就搞定了。

