2015-10-16 60 views
1

我一直在試圖在後端使用SQLAlchemy來獲得體面大小的項目。我有跨多個文件的表模型,它自己的文件中有一個聲明基,還有一個幫助文件來包裝常用的SQLAlchemy函數和驅動程序文件。SQLAlchemy從ORM實例化對象時出現AttributeError失敗:mapper

我正在上傳數據,然後決定添加一列。由於這只是測試數據,我認爲最簡單的方法是刪除所有表並重新開始......然後,當我嘗試重新創建模式和表時,常用的聲明式基類突然有空元數據。我通過導入類聲明文件解決了這個問題 - 奇怪,因爲我之前不需要這些導入 - 並且能夠成功重新創建模式。

但現在,當我再次嘗試創建對象,我得到一個錯誤:

AttributeError: mapper 

現在我完全糊塗了!有人可以解釋這裏發生了什麼嗎?在我放棄架構之前它工作正常,現在我無法正常工作。

這是我設置的骨架:

base.py

from sqlalchemy.ext.declarative import declarative_base 
Base = declarative_base() 

models1.py

from base import Base 
class Business(Base): 
    __tablename__ = 'business' 
    id = Column(Integer, primary_key=True) 

models2.py:

from base import Base 
class Category(Base): 
    __tablename__ = 'category' 
    id = Column(Integer, primary_key=True) 

helper.py:

from base import Base 

# I didn't need these two imports the first time I made the schema 
# I added them after I was just getting an empty schema from base.Base 
# but have no idea why they're needed now? 
import models1 
import models2 

def setupDB(): 
    engine = getDBEngine(echo=True) # also a wrapped func (omitted for space) 
    #instantiate the schema 
    try: 
     Base.metadata.create_all(engine, checkfirst=True) 
     logger.info("Successfully instantiated Database with model schema") 
    except: 
     logger.error("Failed to instantieate Database with model schema") 
     traceback.print_exc() 

def dropAllTables(): 
    engine = getDBEngine(echo=True) 
    # drop the schema 
    try: 
     Base.metadata.reflect(engine, extend_existing=True) 
     Base.metadata.drop_all(engine) 
     logger.info("Successfully dropped all the database tables in the schema") 
    except: 
     logger.error("Failed to drop all tables") 
     traceback.print_exc() 

driver.py:

import models1 
import models2 

#^some code to get to this point 
categories [] 
categories.append(
       models2.Category(alias=category['alias'], 
           title=category['title']) # error occurs here 
       ) 

堆棧跟蹤:(出於完整性)

File "./main.py", line 16, in <module> 
yelp.updateDBFromYelpFeed(fname) 
    File "/Users/thomaseffland/Development/projects/health/pyhealth/pyhealth/data/sources/yelp.py", line 188, in updateDBFromYelpFeed 
    title=category['title']) 
    File "<string>", line 2, in __init__ 
    File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/orm/instrumentation.py", line 347, in _new_state_if_none 
    state = self._state_constructor(instance, self) 
    File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 747, in __get__ 
    obj.__dict__[self.__name__] = result = self.fget(obj) 
    File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/orm/instrumentation.py", line 177, in _state_constructor 
    self.dispatch.first_init(self, self.class_) 
    File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/event/attr.py", line 256, in __call__ 
    fn(*args, **kw) 
    File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 2825, in _event_on_first_init 
    configure_mappers() 
    File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 2721, in configure_mappers 
    mapper._post_configure_properties() 
    File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 1710, in _post_configure_properties 
    prop.init() 
    File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/orm/interfaces.py", line 183, in init 
    self.do_init() 
    File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 1616, in do_init 
    self._process_dependent_arguments() 
    File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 1673, in  _process_dependent_arguments 
    self.target = self.mapper.mapped_table 
    File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 833, in __getattr__ 
    return self._fallback_getattr(key) 
    File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 811, in _fallback_getattr 
    raise AttributeError(key) 
AttributeError: mapper 

我知道這篇文章很長,但我想給完整的圖片。首先,我很困惑爲什麼base.Base模式首先是空的。現在我很困惑爲什麼Categories對象缺少映射器!

任何幫助/見解/建議非常感謝,謝謝!

編輯:

所以模型文件和helper.py處於supackage和driver.py實際上是在同級子包一個文件,它的代碼被包裝在一個函數。該驅動程序功能由包級主文件調用。所以我不認爲這可能是因爲SQLAlchemy沒有時間來初始化? (如果我正確地理解了答案),這裏是主文件(的相關部分)的樣子:

main。潘岳:

import models.helper as helper 
helper.setupDB(echo=true) # SQLAlchemy echos the correct statements 

import driverpackage.driver as driver 
driver.updateDBFromFile(fname) # error occurs in here 

driver.py實際上看起來像:

import ..models.models1 
import ..models.models2 

def updateDBFromFile(fname): 
    #^some code to get to this point 
    categories [] 
    categories.append(
        models2.Category(alias=category['alias'], 
            title=category['title']) # error occurs here 
        ) 
    # a bunch more code 

編輯2: 我開始懷疑潛在的問題是一樣的道理我突然需要導入所有模型以在helper.py中設置架構。如果我打印導入的模型對象的表,他們沒有約束的元數據或模式:

print YelpCategory.__dict__['__table__'].__dict__ 
#### 
{'schema': None, '_columns': <sqlalchemy.sql.base.ColumnCollection object at 0x102312ef0>, 
'name': 'yelp_category', 'description': 'yelp_category', 
'dispatch': <sqlalchemy.event.base.DDLEventsDispatch object at 0x10230caf0>, 
'indexes': set([]), 'foreign_keys': set([]), 
'columns': <sqlalchemy.sql.base.ImmutableColumnCollection object at 0x10230fc58>, 
'_prefixes': [], 
'_extra_dependencies': set([]), 
'fullname': 'yelp_category', 'metadata': MetaData(bind=None), 
'implicit_returning': True, 
'constraints': set([PrimaryKeyConstraint(Column('id', Integer(), table=<yelp_category>, primary_key=True, nullable=False))]), 'primary_key': PrimaryKeyConstraint(Column('id', Integer(), table=<yelp_category>, primary_key=True, nullable=False))} 

我不知道爲什麼,從創建數據庫基礎中的元數據是不是gettng約束?

+0

是否在Category Category中的此行出現錯字或粘貼錯誤? '__tablename__ ='business'' – brandaemon

+0

是的,我已經修復了 – Taaam

+0

[Python SqlAlchemy - AttributeError:mapper]的可能重複(https://stackoverflow.com/questions/45534903/python-sqlalchemy-attributeerror-mapper) –

回答

0

問題似乎已經消失,所以我會發布我的工作。這很簡單。我重構了代碼以明確提供類和經典映射器,而不是使用聲明性基礎,並且所有工作都再次正常......

0

我想這個錯誤是因爲你在Python模塊級上執行你的代碼而發生的。 Python在導入模塊時執行此代碼。

  • 將您的代碼移到一個函數。

  • 正確初始化SQLAlchemy後調用該函數。

  • create_all()需要安裝應用程序時,只調用一次,因爲創建數據庫中的表

  • 持續需要DBSession.configure(bind=engine)或相關的它會告訴模型的數據庫連接它們是相關的。這個問題沒有解決。

+0

嗯,我不這麼認爲?這個例子稍微簡化了一些,實際上模型和驅動程序都在單獨的子包中,驅動文件實際上是一個函數。包級主文件調用驅動程序文件。我將添加一個編輯來正確解釋這一點。 – Taaam

+0

爲答案增加了一些想法。 –

+0

我有'''setupDB() - > create_all'''來顯示SQLAlchemy被加載並且知道模型,當我調用'updateDBFromFile''的時候。在實踐中,該行被註釋掉。 '''getDBSession(echo = True)'''''''''''''''''''''''''''''''' ''' – Taaam