【问题标题】:SQLAlchemy instantiate object from ORM fails with AttributeError: mapperSQLAlchemy 从 ORM 实例化对象失败,出现 AttributeError: mapper
【发布时间】:2016-01-14 15:55:36
【问题描述】:

我一直在尝试在后端使用 SQLAlchemy 开发一个体面的项目。我有跨多个文件的表模型,在它自己的文件中的声明性基础,以及用于包装常见 SQLAlchemy 函数和驱动程序文件的帮助文件。

我正在上传数据,然后决定添加一列。由于这只是测试数据,我认为最简单的方法是删除所有表并重新开始......然后当我尝试重新创建模式和表时,通用声明性基类突然有空的元数据。我通过导入类声明文件解决了这个问题——很奇怪,因为我以前不需要这些导入——并且它能够成功地重新创建架构。

但现在当我再次尝试创建对象时,出现错误:

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 在一个子包中,driver.py 实际上是同级子包中的一个文件,它的代码被包装在一个函数中。此驱动程序函数由包级主文件调用。所以我不认为这可能是因为 SQLAlchemy 还没有来得及初始化? (如果我正确理解答案)这是主文件(的相关部分)的样子:

ma​​in.py:

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

我想知道为什么创建数据库的基础中的元数据没有被绑定?

【问题讨论】:

标签: python sqlalchemy


【解决方案1】:

我猜这个错误的发生是因为你在 Python 模块级别上执行你的代码。此代码在 Python 导入模块时执行。

  • 将代码移动到函数中。

  • 在 SQLAlchemy 正确初始化后调用函数。

  • create_all()在安装应用时只需要调用一次,因为创建的表在数据库中持久化

  • 你需要DBSession.configure(bind=engine) 或相关的,它将告诉模型它们与哪个数据库连接相关。问题中缺少这一点。

【讨论】:

  • 嗯,我不这么认为?这是一个稍微简化的例子,实际上模型和驱动程序在单独的子包中,驱动程序文件实际上是一个函数。包级主文件调用驱动程序文件。我将添加一个编辑以正确解释这一点。
  • 为答案添加了一些想法。
  • 我有 setupDB() -&gt; create_all 表明 SQLAlchemy 已加载并知道模型,当我调用 updateDBFromFile 时。实际上,该行已被注释掉。我也有代码在getDBSession(echo=True) 中获取绑定会话:这个包装函数配置引擎,并返回return sessionmaker(bind=getDBEngine(echo=echo))()
【解决方案2】:

这个问题似乎已经消失了,所以我会发布我的工作。这很简单。我重构了代码以显式提供类和经典映射器,而不是使用声明性基础,一切都再次正常运行......

【讨论】:

    猜你喜欢
    • 2021-05-09
    • 1970-01-01
    • 2021-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-11
    • 1970-01-01
    相关资源
    最近更新 更多