Artist
与一个 Album
, 两条 flush
令人感觉相当不适.def save():
artist = Artist(name='aki misawa')
session = Session()
try:
session.add(artist)
session.flush() # 0
album = Album(name='stella musica', artist_id=artist.artist_id)
session.add(album)
session.flush() # 1
session.commit()
finally:
session.close()
sqlalchemy.orm.relationship
来改善这块代码.import sqlalchemy as sqla
import sqlalchemy.orm as sqlorm
from sqlalchemy.ext.declarative import declarative_base as sqla_declarative_base
Base = sqla_declarative_base()
# use MEMORY, not a database file.
# and disable SQL echo
engine = sqla.create_engine('sqlite:///:memory:', echo=False)
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 = sqlorm.relationship(Artist)
Artist
与 Album
定义完成后, 再用 relationship
为 Album
补上一个类成员, 表示它与 Artist
之间的关系.这样一来, SQLAlchemy 就能根据此
relationship
, 从对象关系中产生外键值, 比如之前的 save
函数可以变成这个样子Session = sqlorm.scoped_session(sqlorm.sessionmaker(bind=engine))
def save():
artist = Artist(name='aki misawa')
album = Album(name='stella musica', artist=artist)
session = Session()
try:
session.add(album)
session.flush()
session.commit()
finally:
session.close()
album
即可, 不需要去理会 artist
.来写个函数查一下数据表
def list_all():
session = Session()
try:
print '= Artists ='
for a in session.query(Artist).all():
print a.name
for album in a.albums:
print '- Album:', album.name
print ''
print '= Albums ='
for a in session.query(Album).all():
print a.name
print '+ Artist:', a.artist.name
finally:
session.close()
if __name__ == '__main__':
save()
list_all()
session.query
来查询与数据表关联的类型对象, all()
调用表示全部取出.外键数据需要保持会话才能取得, 也就是说如果上述代码被修改成了
def list_all_albums():
session = Session()
try:
return session.query(Album).all()
finally:
session.close()
if __name__ == '__main__':
save()
for a in list_all_albums():
print a.name
print '+ Artist:', a.artist.name # ERROR
Album
对象的 artist
域时发生错误.现在可以从
Album
得到 Artist
对象, 但是反过来却不行. 那么照猫画虎, 再回头给 Artist
补个 relationship
试试.class Artist(Base):
__tablename__ = 'artist'
artist_id = sqla.Column('id', sqla.Integer, primary_key=True)
name = sqla.Column('name', sqla.String)
albums = sqlorm.relationship(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)
Artist
定义的时候, Album
还没有呢. 所以只能把这一行丢到后面去了, 如class Artist(Base):
__tablename__ = 'artist'
artist_id = sqla.Column('id', sqla.Integer, primary_key=True)
name = sqla.Column('name', sqla.String)
# albums = sqlorm.relationship(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)
Artist.albums = sqlorm.relationship(Album) # put it here
Album
里面的关系声明也给扒到外面去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 = sqlorm.relationship(Artist)
Artist.albums = sqlorm.relationship(Album)
Album.artist = sqlorm.relationship(Artist) # put it here
def save():
artist0 = Artist(name='aki misawa')
artist1 = Artist(name='katou emiri')
album0 = Album(name='stella musica', artist=artist0)
album1 = Album(name='hoshikage no ama no hara', artist=artist0)
album2 = Album(name='jump!', artist=artist1)
session = Session()
try:
session.add(album0)
session.add(album1)
session.add(album2)
session.flush()
session.commit()
finally:
session.close()
def list_all():
session = Session()
try:
print '= Artists ='
for a in session.query(Artist).all():
print a.name
print ''
print '= Albums ='
for a in session.query(Album).all():
print a.name
print '+ Artist:', a.artist.name
finally:
session.close()
if __name__ == '__main__':
save()
list_all()
Artist
对象的 albums
删去个别数据时, 被删除的 Album
数据不会同步到数据库. 这时就需要引入更多配置了. 敬请关注下节: 关系的级联.