2016-03-07 29 views
4

在SQLAlchemy中可以將現有數據庫表自動映射到類中,但是會覆蓋某些表的某些字段嗎?我正在酸洗MetaData對象,因爲它需要一些時間,它包含所有表格,但是當我試圖重寫某些對象時,它引發了一個異常,即MetaData對象未綁定到引擎或連接。提高SQLAlchemy自動映射數據並覆蓋一些列

from sqlalchemy.ext.automap import automap_base 
from sqlalchemy import create_engine, MetaData, Column, String, Integer 
import os, pickle 

class MetadataCache(object): 
    def __init__(self, engine, schema): 
     self.engine = engine 
     self.schema = schema 
     self.metadata = None 

    @property 
    def cache_name(self): 
     final_name = '{0}.{1}.cache'.format(self.engine.url.database, 
              self.schema) 
     return final_name 

    def get_or_create_metadata(self): 

     if os.path.exists(self.cache_name): 
      with open(self.cache_name, 'r') as cachefile: 
       self.metadata = pickle.load(cachefile) 
     else: 
      self.metadata = MetaData() 
      self.metadata.reflect(bind=self.engine, schema=self.schema) 
      with open(self.cache_name, 'w') as cachefile: 
       pickle.dump(self.metadata, cachefile) 

     return self.metadata 

engine = create_engine('...') 
metadata = MetadataCache(engine, 'schemaname').get_or_create_metadata() 
Base = automap_base(metadata=metadata) 


class User(Base): 
    __tablename__ = 'user' 

    id = Column('id', Integer, primary_key=True) 
    name = Column('name', String) 

class Profile(Base): 
    __tablename__ = 'profile' 
    id = Column('id', Integer, primary_key=True) 
    userid = Column('userid', ForeignKey('user.id')) 

Base.prepare(reflect=True) 

回答

1

的錯誤,因爲Base擁有(你傳遞給automap_base構造函數)的元數據未綁定到發動機,也不應該。這意味着你必須通過一個綁定到Base.prepare

此外,由於您手動反映元數據,因此不應該讓Base.prepare這樣做。

你的最後一行改成這樣:

Base.prepare(engine) 

編輯:當然,我在想Base.prepare需要發動機做了反映,但因爲你是通過預先反映MetaData(),你可以使用:

Base.prepare() 

編輯:

在回答下面的評論,請注意,您必須通過extend_existing=TrueTable

class User(Base): 
    __tablename__ = 'user' 
    __table_args__ = {'extend_existing': True} 

    id = Column('id', Integer, primary_key=True) 
    name = Column('name', String) 
+0

問題,至少據我所知,是我們想用剛醃製的元數據,而不引擎(最初用於創建元數據)必須可用(可能因爲數據庫不可用)。你能想到一個解決方法,可以做到這一點? – jcrudy

+0

事實上,我已經混淆了思考答案,引擎不需要傳遞給'Base.prepare',我會編輯答案。 – RazerM

+0

問題中的示例實際上並不是自包含的,因此我在此處創建了一個自包含的版本:https://gist.github.com/jcrudy/fb30f079dfcf29fc6e3bd97b037eee1a。當我運行它(將你的建議更改爲最後一行)時,我得到sqlalchemy.exc.InvalidRequestError:表'user'已經爲此MetaData實例定義。指定'extend_existing = True'來重新定義現有Table對象上的選項和列。實際上,錯誤發生在用戶類的定義上。 – jcrudy