python - SQLAlchemy: cascade delete -
i must missing trivial sqlalchemy's cascade options because cannot simple cascade delete operate correctly -- if parent element deleted, children persist, null foreign keys.
i've put concise test case here:
from sqlalchemy import column, integer, foreignkey sqlalchemy.orm import relationship sqlalchemy import create_engine sqlalchemy.orm import sessionmaker sqlalchemy.ext.declarative import declarative_base base = declarative_base() class parent(base): __tablename__ = "parent" id = column(integer, primary_key = true) class child(base): __tablename__ = "child" id = column(integer, primary_key = true) parentid = column(integer, foreignkey(parent.id)) parent = relationship(parent, cascade = "all,delete", backref = "children") engine = create_engine("sqlite:///:memory:") base.metadata.create_all(engine) session = sessionmaker(bind=engine) session = session() parent = parent() parent.children.append(child()) parent.children.append(child()) parent.children.append(child()) session.add(parent) session.commit() print "before delete, children = {0}".format(session.query(child).count()) print "before delete, parent = {0}".format(session.query(parent).count()) session.delete(parent) session.commit() print "after delete, children = {0}".format(session.query(child).count()) print "after delete parent = {0}".format(session.query(parent).count()) session.close() output:
before delete, children = 3 before delete, parent = 1 after delete, children = 3 after delete parent = 0 there simple, one-to-many relationship between parent , child. script creates parent, adds 3 children, commits. next, deletes parent, children persist. why? how make children cascade delete?
the problem sqlalchemy considers child parent, because defined relationship (it doesn't care called "child" of course).
if define relationship on parent class instead, work:
children = relationship("child", cascade="all,delete", backref="parent") (note "child" string: allowed when using declarative style, able refer class not yet defined)
you might want add delete-orphan (delete causes children deleted when parent gets deleted, delete-orphan deletes children "removed" parent, if parent not deleted)
edit: found out: if really want define relationship on child class, can so, have define cascade on backref (by creating backref explicitly), this:
parent = relationship(parent, backref=backref("children", cascade="all,delete")) (implying from sqlalchemy.orm import backref)
Comments
Post a Comment