[英]Identical databases in Flask-SQLAlchemy
我已經問了一個類似的問題,但我想也許我可以改寫它,或者展示我已經做了些什么來進一步闡明這里發生的事情。
目前我有2個相同的數據庫,我試圖解決這個問題(按照我看到的另一個問題),如下所示:
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()
然后它從第二個數據庫獲得結果。 如果我要切換SubTable類的位置,那么結果是相同的(編輯為了清楚:我的意思是結果來自最后定義的任何綁定,如果它們被切換,它將改為查詢來自'bind2'而不是'bind1',就像它目前所做的那樣)。 我真的不知道該怎么做,所以如果你能以任何方式提供幫助,那將是非常棒的。
謝謝。
編輯:如果這是不可能的(或者你只是知道更好或甚至不同的方式),請告訴我。 如果我可以做兩個不同的數據庫對象之類的事情,那也就是好事,我真的不知道該怎么做或者會有什么樣的含義。
編輯2:經過幾個小時的辛苦工作,我終於得出了如何做到這一點的結論。
在__init__.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個MetaData實例,否則SQLAlchemy會生氣。 事實證明,問題是SQLAlchemy的一個限制。
我不知道__bind_key__
是什么,但是有很多方法可以使用具有多個綁定的單個Session。 會話本身可以直接綁定:為此,SubTable1和SubTable2需要單獨映射而不是繼承層次結構的一部分,因為Session基於最基本映射的類定位綁定。 為了共享相同的MetaData,只需將兩個類映射到同一個Table對象:
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()
這是一種方式。 另外,讓我們實際上只使用兩個不同的MetaData對象,使用mixins很容易:
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()
是的,既然我們有兩個MetaData對象,我們可以直接“綁定”它們,如果我們想要去那條路線:
# ... 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()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.