如果子表中的关联行已删除,我想删除父行。
class Child(Base):
__tablename__ = "children"
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey("parents.id", ondelete='CASCADE'))
class Parent(Base):
__tablename__ = "parents"
id = Column(Integer, primary_key=True)
child = relationship(Child, backref="parent", passive_deletes=True)
如果我删除孩子
child_obj = session.query(Child).first()
session.delete(child_obj)
session.commit()
它确实删除了子对象obj,但父对象保持原样。我也想使用级联删除父级。
答案 0 :(得分:1)
您可以阅读以下主题: Linking Relationships with Backref
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String)
addresses = relationship("Address", backref="user")
class Address(Base):
__tablename__ = 'address'
id = Column(Integer, primary_key=True)
email = Column(String)
user_id = Column(Integer, ForeignKey('user.id'))
您可以在子类中定义它:
parent = relationship(Parent, backref=backref("children", cascade="all,delete"))
答案 1 :(得分:0)
您所指的行为有点简单。但是一旦应用程序变大,您将需要更复杂的方法。我个人为每个类实现一个静态方法remove
。它需要id
和其他任何必要的参数才能知道删除方案。
已经给出了答案...但这只是效率低下的方法,仅举一个例子。
class Child(Base):
__tablename__ = "children"
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey("parents.id", ondelete='CASCADE'))
@staticmethod
def remove(_id_):
child = Child.query().get(_id_)
Parent.remove(child.parent_id)
session.delete(child)
class Parent(Base):
__tablename__ = "parents"
id = Column(Integer, primary_key=True)
child = relationship(Child, backref="parent", passive_deletes=True)
@staticmethod
def remove(_id_):
parent = parent.query().get(_id_)
session.delete(parent)
例如,如果您在Column
类中添加了一个名为is_old
的{{1}}-那是二进制整数0或1,并且想要删除其中的Child
具有parent
的{{1}},这将是非常容易的任务。
答案 2 :(得分:0)
对于简单的 * 情况,您可以通过创建listener来做到这一点,该拦截器拦截Child
实例的删除,如果没有其他子代,则删除父代。
import sqlalchemy as sa
@sa.event.listens_for(sessionmaker, 'persistent_to_deleted')
def intercept_persistent_to_deleted(session, object_):
# We are only interested in instances of Child.
if not isinstance(object_, Child):
return
p = object_.parent
# Handle null parents.
if p is None:
return
cs = session.query(Child).filter(Child.parent == p).count()
if cs == 0:
session.delete(p)
* 我建议您进行彻底的测试,看看您的代码是否在执行删除会话的工作,例如在同一会话中与删除的孩子的父母一起创建新的孩子。监听器在这种情况下起作用:
c = session.query(Child).first()
p = c.parent
session.delete(c)
c1 = Child(parent=p)
session.add(c1)
session.commit()
但尚未经过任何更复杂的测试。