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