2013-06-14 21 views
6

Daha önce benzer bir soru sordum, ama belki de onu yeniden ifade edebilirim veya daha neler yaptığımı gösterdiğimi düşündüm.Flask-SQLAlchemy'deki aynı veritabanları

Şu anda 2 özdeş veritabanları var ve böyle (gördüğüm başka bir soru göre) problemini çözmeye çalıştı ettik:

class BaseTable(db.Model): 
    __tablename__ = 'TableName' 
    col = db.Column(db.Integer) 

class SubTable1(BaseTable): 
    __bind_key__ = 'bind1' 

class SubTable2(BaseTable): 
    __bind_key__ = 'bind2' 

şimdi en son bağlama bu sorun olduğunu her yerde kullanılır, bu yüzden eğer bunu başka bir yerde yaparsam:

SubTable1.query.filter_by(col=12).all() 

Daha sonra ikinci veritabanından sonuçlar alır. Eğer SubTable sınıflarının konumlarını değiştireceksem, sonuçlar aynıdır (Netlik için Düzenle: Sonuçta, sonuçların ne olursa olsun bağlamanın son olarak tanımlandığı, değiştirileceklerse, bunun yerine sorgulanacağı anlamına gelir. Şu anda yaptığı gibi 'bind1' yerine 'bind2'. Ne yapacağımı gerçekten bilmiyorum, bu yüzden eğer herhangi bir şekilde yardım ederseniz harika olurdu.

Teşekkürler.

DÜZENLEME: Bunu yapmak imkansızsa (veya daha iyi ya da farklı bir yolla biliyorsanız), lütfen bana bildirin. İki farklı db nesnesine sahip olmak gibi bir şey yapabilseydim, bu da iyi olurdu, bunu nasıl yapacağımı gerçekten bilmiyorum ya da ne tür etkileri olacaktı.

DÜZEN 2: Bunu saatlerce ve saatlerce beklettikten sonra, bunun nasıl yapılacağına dair bir sonuca vardım. __init__.py olarak

:

models.py olarak
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) 

bu saçmalığa nedeni bağlar sadece bir kez değil, tanımlanmış değişti ve hiçbir iki tablo adları edilebilmesidir Bağlantılar farklı olsa bile aynı olabilir. Yani 2 MetaData örneğini yapmak zorundasınız, yoksa SQLAlchemy delirir. Yani sorun, SQLAlchemy'de bir sınırlama ortaya çıkıyor.

cevap

8

__bind_key__'un ne olduğunu bilmiyorum, ancak birden çok bağlama ile tek bir Oturum kullanmaya ilişkin birçok yaklaşım var. Oturum doğrudan kendiliğinden bağlanabilir: Bunu yapmak için, SubTable1 ve SubTable2'nin, temelde en çok eşlenen sınıfa dayanarak bağlamayı saptadığı için, bir miras hiyerarşisinin parçası değil, tek tek eşlenmesi gerekir. aynı meta veri paylaşmak için, sadece aynı Tablo nesnesine hem sınıfları haritası: tek yön var

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

. Bir diğeri, en aslında sadece iki farklı MetaData nesneleri, yeterince kolay olan katmalar kullanalım:

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

ve orada iki MetaData nesneleri beri evet, yapabiliriz "bağlamak" onları doğrudan, biz o yoldan gitmek istiyorum :

# ... 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() 
İlgili konular