我有一个由关联表链接的多对多关系,如下所示:
left_right_association_table = Table("left_right_association_table", Base.metadata,
Column('leftside_id', Integer, ForeignKey('leftside_table.id')),
Column('rightside_id', Integer, ForeignKey('rightside_table.id'))
)
class LeftSide(Base):
...
rightside_members = relationship("RightSide", secondary=left_right_association_table, backref="leftside", lazy="joined")
...
class RightSide(Base):
...
现在我有一个LeftSide
实例,RightSide
实例的list
作为其rightside_members
属性:
ls = LeftSide(**kw)
rs1 = RightSide(**kw)
rs2 = RightSide(**kw)
ls.rightside_members.append(rs1)
ls.rightside_members.append(rs2)
然后,我想删除一个列表成员:rs2
.
步骤1:我复制rightside_members
列表:
updated_rightside_members = [RightSide(**rs_attrs) for rs_attrs in ls.rightside_members] # each `rs` object already has primary key
updated_rightside_members.pop() # remove the second item from the list
步骤2:我从数据库中检索ls
:
old_ls = db_session.query(LeftSide).filter(LeftSide_id == ls.id).one()
步骤3:我将updated_rightside_members添加到old_ls
:
old_ls.rightside_members = updated_rightside_members
步骤4:commit to database.
db_session.commit()
然后我得到这个错误:
sqlite3.IntegrityError: UNIQUE constraint failed: rightside_table.id
在我看来,SQLAlchemy认为我试图将复制的rs1
放回数据库,而不是从数据库中删除它的兄弟rs2
。
我应该如何做这个删除操作?
我已经解决了这个问题。首先,我真的想指出,仔细阅读文档是有帮助的。使用映射类初始化实例并不意味着会话知道这个对象,至少在使用Session.add()
方法之前是这样。
- 决定传入参数是否包含代表实例主键的
id
。如果是,那么正确的方法不是初始化它,而是从数据库中查询它。这样,Session
将确保查询的对象在其identity map
中具有唯一的对象id。 - 如果不包含
id
属性,则初始化它,并将其添加到成员列表中。