在之前代码的基础上添加下面的函数
def remove_album(name):
session = Session()
try:
for a in session.query(Album).filter(Album.name == name).all():
session.delete(a)
session.flush()
session.commit()
finally:
session.close()
Album 类型, 然后调用查询对象的 filter 函数, 指定列 name 的值严格等于该 name 参数. 接下来, 将查询得到的对象逐个删除.来看看搞起来如何
if __name__ == '__main__':
save()
remove_album('stella musica')
list_all()
那么, 接下来试试删
Artistdef remove_artist(name):
session = Session()
try:
for a in session.query(Artist).filter(Artist.name == name).all():
session.delete(a)
session.flush()
session.commit()
finally:
session.close()
if __name__ == '__main__':
save()
remove_artist('katou emiri')
list_all()
崩盘之前的几行输出似乎是这样子的
= Albums =
stella musica
+ Artist: aki misawa
hoshikage no ama no hara
+ Artist: aki misawa
jump!
+ Artist:
remove_artist 确实从数据库中删去了名字为 'katou emiri' 的那个值, 因此名为 'jump!' 的那个 Album 实例的 artist 域成了 None, 悲剧就发生了.要解决这个问题, 就得在
Album 与 Artist 的关联关系上动动手脚, 加上级联信息.class Artist(Base):
__tablename__ = 'artist'
artist_id = sqla.Column('id', sqla.Integer, primary_key=True)
name = sqla.Column('name', sqla.String)
class Album(Base):
__tablename__ = 'album'
album_id = sqla.Column('id', sqla.Integer, primary_key=True)
name = sqla.Column('name', sqla.String)
artist_id = sqla.Column('artist', sqla.ForeignKey('artist.id'))
# Artist.albums = sqlorm.relationship(Album)
# Album.artist = sqlorm.relationship(Artist)
Album.artist = sqlorm.relationship(
Artist, backref=sqlorm.backref('albums', cascade='all'))
这一次删去了
Artist 向 Album 的 relationship, 同时为 Album 向 Artist 的 relationship 添加了参数 backref, 表示反向引用到 Artist 实例的 albums 成员 (上面删去 Artist.albums 这个关联就是为了给 backref 腾个位置出来, 所以 list_all 或者其它任何函数都可以查询得到的 Artist 实例的 albums 成员), 并且在删除 Artist 实例时级联删除对应的 Album 实例集, 而反过来删则不会.最后来尝试修改数据. 下面是一个示例函数
def modify():
session = Session()
try:
artists = session.query(Artist).filter(Artist.name.like('%isa%')).all()
artist = artists[0]
artist.name = 'misawa aki'
artist.albums = filter(lambda a: a.name.startswith('ho'), artist.albums)
artist.albums.append(Album(name='natuhana no kageokuri', artist=artist))
session.flush()
session.commit()
finally:
session.close()
if __name__ == '__main__':
save()
modify()
list_all()
= Artists =
misawa aki
- Album: hoshikage no ama no hara
- Album: natuhana no kageokuri
katou emiri
- Album: jump!
= Albums =
stella musica
+ Artist:
'stella musica' 的 Album 实例确实已经跟名为 misawa aki (这个实例对象的名字修改也完成了) 的实例脱离关系了, 所以在前一段的输出看不到, 但它实际上还没有从数据库中删去, 因此取得该对象时, 它的 artist 域为 None.为了确保从反过来, 从集合中删除实例的引用也同步删除表中数据, 需要修改级联方式, 添加
'delete-orphan' 项. 另外, 既然 Artist.albums 这个项目已经移除了, 所以索性把 Album.artist 直接放回 Album 类声明中去好了.class Album(Base):
__tablename__ = 'album'
album_id = sqla.Column('id', sqla.Integer, primary_key=True)
name = sqla.Column('name', sqla.String)
artist_id = sqla.Column('artist', sqla.ForeignKey('artist.id'))
artist = sqlorm.relationship(
Artist, backref=sqlorm.backref('albums',
cascade='all,delete-orphan'))
modify() 就没问题了.PS: 如果需求某个表中建立多个外键, 且它们引用相同的另一张表, 请移步这里.