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的级联删除配置方法

1 回复

在SQLAlchemy里配置级联删除,主要是在定义relationship时设置cascade参数。最常用的选项是"all, delete-orphan",它能确保父对象被删除时,相关联的子对象也被删除。

下面是一个完整的例子,假设我们有两个模型:ParentChild,它们是一对多的关系。

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()

代码解释:

  1. 模型定义Parent模型中的children关系字段是关键。cascade='all, delete-orphan'意味着:
    • all:包含了所有级联操作(如save-update, merge, delete等)。
    • delete-orphan:当子对象从父对象的集合中移除(即成为“孤儿”)时,也会被删除。这在配置级联删除时通常是必需的组合。
  2. 外键Child表中的parent_id是外键,指向parents.id,这是关系的基础。
  3. 测试:代码创建了一个父对象和两个子对象,然后删除父对象。提交后查询子表,结果为空,证明级联删除生效。

其他常用cascade选项:

  • "save-update":默认包含,允许通过父对象添加子对象。
  • "delete":仅删除级联,但不处理“孤儿”。
  • 你可以组合多个选项,例如cascade="save-update, merge, delete"

一句话总结:在父模型的relationship里加上cascade='all, delete-orphan'就搞定了。

回到顶部