SQLALCHEMY 删除关联对象不会将其从父子对象中删除
SQLALCHEMY deleting Association Object does not delete it from the parent and child
我正在尝试删除关联对象。它已从 table 中删除,但父对象的集合中仍有子对象。这是我的代码:
import sqlalchemy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, ForeignKey
from sqlalchemy.orm import sessionmaker, relationship
engine = sqlalchemy.create_engine('sqlite:///:memory:')
Base = declarative_base()
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
children = relationship("Association", back_populates="parent")
def __repr__(self) -> str:
return f"Parent: {self.id}, {self.children}"
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
parents = relationship("Association", back_populates="child")
def __repr__(self) -> str:
return f"Child: {self.id}, {self.parents}"
class Association(Base):
__tablename__ = 'association'
parent_id = Column(Integer, ForeignKey('parent.id'), primary_key=True)
child_id = Column(Integer, ForeignKey('child.id'), primary_key=True)
child = relationship("Child", back_populates="parents")
parent = relationship("Parent", back_populates="children")
def __repr__(self) -> str:
return f"Association: ({self.parent}); ({self.child};)"
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine, autoflush=False, autocommit=False, expire_on_commit=False)
session = Session()
p = Parent()
c = Child()
session.add(p)
session.add(c)
session.commit()
association = Association(parent=p, child=c)
session.add(association)
session.commit()
assert session.query(Association).all()
assert session.query(Parent).all()[0].children
assert session.query(Child).all()[0].parents
session.delete(association)
session.commit()
assert not session.query(Association).all()
assert not session.query(Parent).all()[0].children
assert not session.query(Child).all()[0].parents
现在,当我删除一个关联对象并从 table 关联中查询它时,它就消失了。但是,如果我查询父对象或子对象,关联仍在它们的集合字段中。我如何配置它,所以当我删除关联对象时,该对象也会从父集合和子集合中完全删除。
这是因为您设置了 expire_on_commit=False
。这意味着任何时候您提交,现有实例 不会 过期。
如果将其设置为 True(默认值),您将获得预期的行为。
如果出于某种原因不需要使用 expire_on_commit=True
,您可以使用 Session#expire or Session#expire_all.
手动使实例过期
我正在尝试删除关联对象。它已从 table 中删除,但父对象的集合中仍有子对象。这是我的代码:
import sqlalchemy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, ForeignKey
from sqlalchemy.orm import sessionmaker, relationship
engine = sqlalchemy.create_engine('sqlite:///:memory:')
Base = declarative_base()
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
children = relationship("Association", back_populates="parent")
def __repr__(self) -> str:
return f"Parent: {self.id}, {self.children}"
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
parents = relationship("Association", back_populates="child")
def __repr__(self) -> str:
return f"Child: {self.id}, {self.parents}"
class Association(Base):
__tablename__ = 'association'
parent_id = Column(Integer, ForeignKey('parent.id'), primary_key=True)
child_id = Column(Integer, ForeignKey('child.id'), primary_key=True)
child = relationship("Child", back_populates="parents")
parent = relationship("Parent", back_populates="children")
def __repr__(self) -> str:
return f"Association: ({self.parent}); ({self.child};)"
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine, autoflush=False, autocommit=False, expire_on_commit=False)
session = Session()
p = Parent()
c = Child()
session.add(p)
session.add(c)
session.commit()
association = Association(parent=p, child=c)
session.add(association)
session.commit()
assert session.query(Association).all()
assert session.query(Parent).all()[0].children
assert session.query(Child).all()[0].parents
session.delete(association)
session.commit()
assert not session.query(Association).all()
assert not session.query(Parent).all()[0].children
assert not session.query(Child).all()[0].parents
现在,当我删除一个关联对象并从 table 关联中查询它时,它就消失了。但是,如果我查询父对象或子对象,关联仍在它们的集合字段中。我如何配置它,所以当我删除关联对象时,该对象也会从父集合和子集合中完全删除。
这是因为您设置了 expire_on_commit=False
。这意味着任何时候您提交,现有实例 不会 过期。
如果将其设置为 True(默认值),您将获得预期的行为。
如果出于某种原因不需要使用 expire_on_commit=True
,您可以使用 Session#expire or Session#expire_all.