2013-06-14 10 views
6

私はすでに同様の質問をしてきましたが、私はそれを言い換えることができたかもしれません。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クラスの場所を切り替えると、結果は同じです(明快にするために編集:バインドが最後に定義されたものから結果が得られることを意味します。現在のように 'bind1'ではなく 'bind2')。私は本当に何をすべきかわからないので、もしあなたが何かを助けることができればそれはすばらしいでしょう。

ありがとうございました。

編集:これを行うには不可能な場合(または、より良い方法や異なる方法を知っている場合)、私にお知らせください。私は2つの異なるdbオブジェクトを持つような何かをすることができれば、それも良いでしょう、私はちょうどそれを行う方法やどのような影響があるのか​​分かりません。

編集2:これを数時間、数時間トールした後、私はついにこれを行う方法について結論に至りました。 __init__.pyで

:models.pyで

db1 = SQLAlchemy(app) 
db2 = SQLAlchemy(app) 

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人のテーブル名バインドが異なる場合であっても同じである可能性があります。したがって、2つのMetaDataインスタンスを作成する必要があります。そうしないと、SQLAlchemyが怒ってしまいます。だから、問題はSQLAlchemyの制限だと分かります。

答えて

8

私は__bind_key__が何であるか分かりませんが、複数のバインドで1つのセッションを使用する方法はたくさんあります。セッション自体は直接バインドすることができます。これを行うには、SubTable1とSubTable2を継承階層の一部ではなく、個別にマップする必要があります。セッションは、一番上にマップされたクラスに基づいてバインドを探します。同じ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() 

これは片方向です。我々はそのルートを移動する場合、

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() 

とはい、私たちはそこに2つのメタデータオブジェクトを持っているので、我々は直接「バインド」彼らすることができます:別の、のは実際にはミックスインで簡単に十分な二つの異なるメタデータ・オブジェクトを、使用してみましょう:

# ... 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() 
関連する問題