使用具有单个sqlalchemy模型的多个数据库

use*_*182 4 python sqlalchemy

我想使用具有单个sqlalchemy数据库模型的多个数据库引擎.

以下情况:我有一个相册软件(python),不同的相册存储在不同的文件夹中.每个文件夹中都有一个单独的sqlite数据库,其中包含有关照片的其他信息.我不想使用单个全局数据库,因为通过这种方式,我可以简单地移动,删除和复制基于文件夹的相册.打开一张专辑非常简单:

创建数据库会话:

maker = sessionmaker(autoflush=True, autocommit=False,
                 extension=ZopeTransactionExtension())
DBSession = scoped_session(maker)
Run Code Online (Sandbox Code Playgroud)

db模型的基类和元数据:

DeclarativeBase = declarative_base()
metadata = DeclarativeBase.metadata
Run Code Online (Sandbox Code Playgroud)

定义数据库模型(缩短):

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')
Run Code Online (Sandbox Code Playgroud)

最后打开连接:

engine = engine_from_config(config, '...')
DBSession.configure(bind=engine)
metadata.bind = engine
Run Code Online (Sandbox Code Playgroud)

这适用于打开一张专辑.现在我想同时打开多个专辑(和数据库连接).每张专辑都有相同的数据库模型,所以我希望能重复使用它.我的问题是模型类定义是从连接到元数据和数据库引擎的声明性基础继承的.我想用不同的工程将类连接到不同的元数据.这可能吗?

PS:我还想通过ORM查询数据库,例如DBSession.query(图片).all()(或DBSession [0],...用于不同数据库上的多个会话 - 所以不是所有图片都有一个查询数据库,但一个ORM样式查询用于查询一个数据库)

uni*_*rio 7

您可以使用多个引擎和会话来实现此目的(您不需要多个元数据):

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()
Run Code Online (Sandbox Code Playgroud)

对于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()
...
Run Code Online (Sandbox Code Playgroud)

如果您需要打开可变数量的数据库,scoped_session可能会有点麻烦.你需要一些方法来跟踪它们.