2011-10-11 160 views
3

我有兩個數據庫隊列的實現(他們使用不同的表),並希望他們使用同一類的對象。所以,他們都看起來很類似:SQLAlchemy - 映射一個類到兩個表

class AbstractDBQueue(object): 
    def __init__(self, tablename): 
     self.tablename = tablename 
     self.metadata = MetaData() 
     self.engine = create_engine('mysql+mysqldb://%s:%[email protected]%s:%d/%s' % (
      settings.DATABASE.get('USER'), 
      settings.DATABASE.get('PASSWORD'), 
      settings.DATABASE.get('HOST') or '127.0.0.1', 
      settings.DATABASE.get('PORT') or 3306, 
      settings.DATABASE.get('NAME') 
     ), encoding='cp1251', echo=True, pool_recycle=7200) 
     self.metadata.bind = self.engine 
     self.session = sessionmaker(bind=self.engine)() 

    def setup_table(self, table, entity_name): 
     self.table = table 
     newcls = type(entity_name, (SMSMessage,), {}) 
     mapper(newcls, table) 
     return newcls 

    def put(self, message=None, many_messages=[]): 
     if message: 
      self.session.add(message) 
     else: 
      for m in many_messages: 
       self.session.add(m) 
     self.session.commit() 

    def get(self, limit=None): 
     if limit: 
      q = self.session.query(self.SMSClass).limit(limit) 
     else: 
      q = self.session.query(self.SMSClass) 
     smslist = [] 
     for sms in q: 
      smslist.append(sms) 
     self.session.expunge_all() 
     return smslist 

class DBQueue(AbstractDBQueue): 
    """ 
    MySQL database driver with queue interface 
    """ 
    def __init__(self): 
     self.tablename = settings.DATABASE.get('QUEUE_TABLE') 
     super(DBQueue, self).__init__(self.tablename) 
     self.logger = logging.getLogger('DBQueue') 
     self.SMSClass = self.setup_table(Table(self.tablename, self.metadata, autoload=True), "SMSQueue") 

class DBWorkerQueue(AbstractDBQueue): 
    """ 
    MySQL database driver with queue interface for separate workers queue 
    """ 

    def __init__(self): 
     self.tablename = settings.DATABASE.get('WORKER_TABLE') 
     super(DBWorkerQueue, self).__init__(self.tablename) 
     self.logger = logging.getLogger('DBQueue') 
     self.SMSClass = self.setup_table(Table(self.tablename, self.metadata, autoload=True), "SMSWorkerQueue") 

    def _install(self): 
     self.metadata.create_all(self.engine) 

SMSMessage是我想使用的類的名稱。該map_class_to_table()功能是一個黑客,我SQLAlchemy的文檔中找到:http://www.sqlalchemy.org/trac/wiki/UsageRecipes/EntityName

不過,這並不似乎幫助 - 當第一個隊列實例映射SMSMessage到它的表,然後我通過所有對象到第二個隊列的put()被隱式轉換爲第一個隊列的映射類,第二個數據庫在session.commit()後仍然爲空。

我需要同時使用這兩個隊列,甚至可能使用線程(我認爲,池連接將是有用的),但我不能使這項工作。你能幫忙嗎?

+0

嗯,如果你先使用第二個隊列,它是否會顛倒順序? –

+0

我剛剛使用繼承重寫了代碼,現在它只是引發了一個錯誤「Class'sms.message.SMSMessage'未映射」。我應該投入輸入對象映射類?這似乎很奇怪。 – Enchantner

回答

0

我認爲你的問題涉及到tablename變量。這是一個class variable,它在您創建班級時定義,並且然後不會更改。所以,對於你的兩個實例,當它們通過self.tablename進行訪問時,它將是相同的。要解決此問題,請將其移動到init函數中,並將其設置爲self.tablename。每次創建新對象時都會初始化它。

+0

我已經更新了主題中的代碼 - 在傳遞tablename作爲構造函數參數的同時重寫爲使用兩個隊列類的繼承。但它也行不通。 – Enchantner

相關問題