Python 炼金术中的相同数据库
我已经问了一个类似的问题,但我想也许我可以重新表述一下,或者展示一下我所做的进一步工作,让大家了解这里正在发生的事情 目前我有两个相同的数据库,我试图解决这个问题(根据我看到的另一个问题),如下所示:Python 炼金术中的相同数据库,python,sqlalchemy,flask,flask-sqlalchemy,Python,Sqlalchemy,Flask,Flask Sqlalchemy,我已经问了一个类似的问题,但我想也许我可以重新表述一下,或者展示一下我所做的进一步工作,让大家了解这里正在发生的事情 目前我有两个相同的数据库,我试图解决这个问题(根据我看到的另一个问题),如下所示: class BaseTable(db.Model): __tablename__ = 'TableName' col = db.Column(db.Integer) class SubTable1(BaseTable): __bind_key__ = 'bind1' c
class BaseTable(db.Model):
__tablename__ = 'TableName'
col = db.Column(db.Integer)
class SubTable1(BaseTable):
__bind_key__ = 'bind1'
class SubTable2(BaseTable):
__bind_key__ = 'bind2'
问题是现在到处都使用最新的绑定,所以如果我在其他地方这样做:
SubTable1.query.filter_by(col=12).all()
然后从第二个数据库获取结果。如果我要切换子表类的位置,那么结果是相同的(为了清晰起见进行编辑:我的意思是,结果来自最后定义的绑定,如果要切换,它将从“bind2”而不是当前的“bind1”进行查询)。我真的不知道该怎么办,所以如果你能提供任何帮助,那就太棒了
谢谢
编辑:如果这是不可能的(或者你只是知道一个更好甚至不同的方法),请让我知道。如果我能做一些事情,比如拥有两个不同的db对象,那也不错,我只是不知道该怎么做,或者这会有什么样的影响
编辑2:经过数小时的辛苦工作,我终于得出了一个关于如何做到这一点的结论
在uuu init_uuuuu.py中:
db1 = SQLAlchemy(app)
db2 = SQLAlchemy(app)
在models.py中:
class Table1(db1.Model):
__tablename__ = 'TableName'
__bind_key__ = 'bind1'
col = db1.Column(db1.Integer)
class Table2(db2.Model):
__tablename__ = 'TableName'
__bind_key__ = 'bind2'
col = db2.Column(db2.Integer)
这种胡说八道的原因是绑定只能定义一次,不能更改,并且没有两个表名可以相同,即使绑定不同。因此,您必须创建2个元数据实例,否则SQLAlchemy会发疯。因此,问题在于SQLAlchemy的局限性。我不知道什么是
\uuu bind\uu key\uuuu
,但是有很多方法可以使用一个会话和多个绑定。会话本身可以直接绑定:为此,子表1和子表2需要单独映射,而不是继承层次结构的一部分,因为会话基于最基本的映射类定位绑定。为了共享相同的元数据,只需将两个类映射到同一个表对象:
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class BaseTable(Base):
__tablename__ = 'some_table'
id = Column(Integer, primary_key=True)
class SubTable1(Base):
__table__ = BaseTable.__table__
class SubTable2(Base):
__table__ = BaseTable.__table__
db1 = create_engine("sqlite:///db1.db", echo=True, logging_name='db1')
db2 = create_engine("sqlite:///db2.db", echo=True, logging_name='db2')
Base.metadata.create_all(db1)
Base.metadata.create_all(db2)
s = Session(binds={SubTable1: db1, SubTable2: db2})
s.add_all([
SubTable1(),
SubTable2(),
SubTable1(),
SubTable2(),
SubTable1(),
])
s.commit()
print s.query(SubTable1).all()
print s.query(SubTable2).all()
这是一种方式。另外,让我们实际上只使用两个不同的元数据对象,使用mixin非常简单:
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class BaseTable(object):
__tablename__ = 'some_table'
id = Column(Integer, primary_key=True)
class DB1(Base):
metadata = MetaData()
__abstract__ = True
class DB2(Base):
metadata = MetaData()
__abstract__ = True
class SubTable1(BaseTable, DB1):
pass
class SubTable2(BaseTable, DB2):
pass
db1 = create_engine("sqlite:///db1.db", echo=True, logging_name='db1')
db2 = create_engine("sqlite:///db2.db", echo=True, logging_name='db2')
DB1.metadata.create_all(db1)
DB2.metadata.create_all(db2)
s = Session(binds={SubTable1: db1, SubTable2: db2})
s.add_all([
SubTable1(),
SubTable2(),
SubTable1(),
SubTable2(),
SubTable1(),
])
s.commit()
print s.query(SubTable1).all()
print s.query(SubTable2).all()
是的,因为我们有两个元数据对象,如果我们想这样做,我们可以直接“绑定”它们:
# ... mapping as before
DB1.metadata.bind = db1
DB2.metadata.bind = db2
DB1.metadata.create_all()
DB2.metadata.create_all()
s = Session() # don't need binds in this case
# ... usage as before
s = Session()