我想使用具有单个sqlalchemy数据库模型的多个数据库引擎。
以下情况: 我有一个相册软件(python),不同的相册存储在不同的文件夹中。每个文件夹中都有一个单独的sqlite数据库,其中包含有关照片的其他信息。我不想使用单个全局数据库,因为通过这种方式,我可以简单地移动,删除和复制基于文件夹的相册。 打开一张专辑非常简单:
创建数据库会话:
maker = sessionmaker(autoflush=True, autocommit=False,
extension=ZopeTransactionExtension())
DBSession = scoped_session(maker)
db model的基类和元数据:
DeclarativeBase = declarative_base()
metadata = DeclarativeBase.metadata
定义数据库模型(缩短):
pic_tag_table = Table('pic_tag', metadata,
Column('pic_id', Integer,
ForeignKey('pic.pic_id'),
primary_key=True),
Column('tag_id', Integer,
ForeignKey('tag.tag_id'),
primary_key=True))
class Picture(DeclarativeBase):
__tablename__ = 'pic'
pic_id = Column (Integer, autoincrement = True, primary_key=True)
...
class Tags(DeckarativeBase):
__tablename__ = 'tag'
tag_id = Column (Integer, autoincrement = True, primary_key=True)
...
pictures = relation('Picture', secondary=pic_tag_table, backref='tags')
最后打开连接:
engine = engine_from_config(config, '...')
DBSession.configure(bind=engine)
metadata.bind = engine
这适用于打开一张专辑。现在我想同时打开多个专辑(和数据库连接)。每张专辑都有相同的数据库模型,所以我希望能重复使用它。我的问题是模型类定义是从连接到元数据和数据库引擎的声明性基础继承的。我想用不同的工程将类连接到不同的元数据。这可能吗?
P.S。:我还想通过ORM查询数据库,例如: DBSession.query(图片).all()(或DBSession [0],...用于不同数据库上的多个会话 - 所以不是一个查询所有数据库中的所有图片,而是查询一个数据库的一个ORM样式查询)
答案 0 :(得分:6)
您可以通过多个引擎和会话实现此目标(您不需要多个元数据):
engine1 = create_engine("sqlite:///tmp1.db")
engine2 = create_engine("sqlite:///tmp2.db")
Base.metadata.create_all(bind=engine1)
Base.metadata.create_all(bind=engine2)
session1 = Session(bind=engine1)
session2 = Session(bind=engine2)
print(session1.query(Picture).all()) # []
print(session2.query(Picture).all()) # []
session1.add(Picture())
session1.commit()
print(session1.query(Picture).all()) # [Picture]
print(session2.query(Picture).all()) # []
session2.add(Picture())
session2.commit()
print(session1.query(Picture).all()) # [Picture]
print(session2.query(Picture).all()) # [Picture]
session1.close()
session2.close()
对于scoped_session
,您也可以创建其中的多个。
engine1 = create_engine("sqlite:///tmp1.db")
engine2 = create_engine("sqlite:///tmp2.db")
Base.metadata.create_all(bind=engine1)
Base.metadata.create_all(bind=engine2)
Session1 = scoped_session(sessionmaker(bind=engine1))
Session2 = scoped_session(sessionmaker(bind=engine2))
session1 = Session1()
session2 = Session2()
...
如果您需要打开可变数量的数据库,scoped_session
可能会有点麻烦。你需要一些方法来跟踪它们。