2013-06-14 8 views
6

나는 이미 비슷한 질문을했지만, 나는 그것을 바꿔 쓸 수 있다고 생각했다. 또는 여기에 무슨 일이 일어나고 있는지 밝히기 위해 내가 한 일을 보여줄 수 있을지도 모른다.Flask-SQLAlchemy의 동일 데이터베이스

현재 나는이 동일한 데이터베이스를 가지고 있고, 나는이 같은 (내가 본 또 다른 질문에 따라) 문제를 해결하기 위해 시도했습니다

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'). 나는 무엇을해야 할지를 정말로 모른다. 그래서 당신이 어떤 식 으로든 도움이된다면 그것은 대단 할 것이다.

감사합니다.

편집 :이 작업을 수행하는 것이 불가능하거나 (더 좋거나 다른 방법을 알고 있다면) 알려주십시오. 두 개의 서로 다른 db 객체를 갖는 것과 같은 작업을 수행 할 수 있다면 좋을 것입니다. 실제로 어떻게 수행 할 것인지 또는 어떤 종류의 함축적 의미가 있는지 알지 못합니다.

EDIT 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 개의 MetaData 인스턴스를 만들어야합니다. 그렇지 않으면 SQLAlchemy가 화를냅니다. 그래서 문제는 SQLAlchemy의 한계라고 밝혀졌습니다.

답변

8

무엇을 모르겠다. __bind_key__이 무엇인지 모르겠다. 그러나 여러 개의 바인딩으로 단일 세션을 사용하는 방법은 여러 가지가있다. 세션 자체는 직접 바인딩 될 수 있습니다.이 작업을 수행하려면 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() 

또,의 실제로 단지 두 개의 서로 다른 메타 데이터 오브젝트 충분히 쉬운 유지 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()