2013-06-14 5 views
6

में समान डेटाबेस पहले से ही एक समान प्रश्न पूछ चुके हैं, लेकिन मैंने सोचा कि शायद मैं इसे फिर से बदल सकता हूं, या दिखा सकता हूं कि मैंने यहां क्या हो रहा है पर कुछ प्रकाश डालने के लिए आगे क्या किया है।फ्लास्क-स्क्लाक्लेमी

वर्तमान में मैं 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() 

फिर यह दूसरे डेटाबेस से परिणाम प्राप्त करता है। अगर मैं सबटेबल वर्गों के स्थानों को स्विच करना चाहता था, तो परिणाम समान होते हैं (स्पष्टता के लिए संपादित करें: जिसके द्वारा मेरा मतलब है कि परिणाम जो कुछ भी बांधते हैं, वे आखिरी बार परिभाषित किए जाते हैं, अगर वे स्विच किए जाते हैं, तो यह इसके बजाय पूछताछ करेगा 'bind2' के बजाय 'bind2' जैसा कि वर्तमान में करता है)। मुझे वास्तव में पता नहीं है कि क्या करना है, इसलिए यदि आप किसी भी तरह से मदद कर सकते हैं तो यह शानदार होगा।

धन्यवाद।

संपादित करें: यदि यह असंभव है (या आप इसे बेहतर या यहां तक ​​कि अलग तरीके से जानते हैं), तो कृपया मुझे बताएं। अगर मैं दो अलग-अलग डीबी ऑब्जेक्ट्स की तरह कुछ कर सकता हूं, तो यह भी अच्छा होगा, मुझे वास्तव में यह नहीं पता कि यह कैसे करना है या किस प्रकार के प्रभाव होंगे।

संपादित करें 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 मेटाडेटा उदाहरण बनाना होगा या फिर SQLAlchemy पागल हो जाता है। तो यह पता चला है कि समस्या SQLAlchemy में एक सीमा है।

उत्तर

8

मुझे नहीं पता कि __bind_key__ क्या है, लेकिन कई बाइंडों के साथ एक सत्र का उपयोग करने के कई दृष्टिकोण हैं। सत्र को सीधे बाध्य किया जा सकता है: ऐसा करने के लिए, सबटेबल 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() 

यह एक तरीका है। एक और, वास्तव में सिर्फ दो अलग मेटाडाटा वस्तुओं, के साथ बहुत आसान 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() 

और हाँ, के बाद से हम दो मेटाडाटा वस्तुओं वहाँ है, हम कर सकते हैं "बाँध" उन्हें सीधे, हम उस मार्ग से जाने के लिए चाहते हैं, तो :

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