Vague Flask-SQLAlchemy error: “AttributeError: mapper”

老子叫甜甜 提交于 2019-12-25 09:25:00

问题


Okay, so I have what seems to be a pretty basic model definition. I don't have the first clue where to begin with this. The only thing I could really think to check is that the table exists, and it does, and the db.create_all() function seems to be able to create the table based on the model definition.

The error seems to be so vague that it doesn't really give me any clues as to where to look. What does the error mean basically? That the Setting class is failing to be mapped? That it doesn't have an attribute named mapper?

Here's the code:

# the model
class Setting(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False)
    description = db.Column(db.String)
    value_type = db.Column(db.String)
    value = db.Column(db.String, nullable=False)

    def get(name):
        setting = db.session.query(Setting).filter(
            Setting.name == name).first()

        if setting.value_type == 'int':
            return int(setting.value)

        if setting.value_type == 'float':
            return float(setting.value)

    def all_settings():
        return {s.name: s.value for s in db.session.query(Setting).all()}

# what's causing the exception:
def load_default_settings():
    print("Loading default settings")

    # in case it helps:
    print(Setting.__dict__)
    # {'__mapper__': <Mapper at 0x7f5633523278; Setting>, 'name': <sqlalchemy.orm.attributes.InstrumentedAttribute object at 0x7f563356eca8>, '__table__': Table('setting', MetaData(bind=None), Column('id', Integer(), table=<setting>, primary_key=True, nullable=False), Column('name', String(), table=<setting>, nullable=False), Column('description', String(), table=<setting>), Column('value_type', String(), table=<setting>), Column('value', String(), table=<setting>, nullable=False), schema=None), '__doc__': None, '_cached_tablename': 'setting', 'description': <sqlalchemy.orm.attributes.InstrumentedAttribute object at 0x7f563356ed58>, 'get': <function Setting.get at 0x7f5633581f28>, '__init__': <function __init__ at 0x7f5636806400>, 'id': <sqlalchemy.orm.attributes.InstrumentedAttribute object at 0x7f563356ebf8>, 'value': <sqlalchemy.orm.attributes.InstrumentedAttribute object at 0x7f563356eeb8>, 'value_type': <sqlalchemy.orm.attributes.InstrumentedAttribute object at 0x7f563356ee08>, 'all_settings': <function Setting.all_settings at 0x7f563350c048>, '__module__': 'gg.settings', '_sa_class_manager': <ClassManager of <class 'gg.settings.Setting'> at 7f563350dd68>} 

    for name, details in SETTINGS.items():
        # calling the Setting constructor below causes the exception
        setting = Setting(
            name=name,
            description=details['description'],
            value=details['value'],
            value_type=details['value_type'])
        db.session.add(setting)

    db.session.commit()

# traceback
Traceback (most recent call last):
  File "main.py", line 5, in <module>
    import gg.cli
  File "/home/nicken/freelance/project/gg/cli/__init__.py", line 75, in <module>
    reset_all()
  File "/home/nicken/freelance/project/gg/cli/__init__.py", line 55, in reset_all
    load_initial_data()
  File "/home/nicken/freelance/project/gg/cli/__init__.py", line 45, in load_initial_data
    load_default_settings()
  File "/home/nicken/freelance/project/gg/settings.py", line 84, in load_default_settings
    value_type=details['value_type']))
  File "<string>", line 2, in __init__
  File "/home/nicken/freelance/project/lib/python3.4/site-packages/sqlalchemy/orm/instrumentation.py", line 347, in _new_state_if_none
    state = self._state_constructor(instance, self)
  File "/home/nicken/freelance/project/lib/python3.4/site-packages/sqlalchemy/util/langhelpers.py", line 764, in __get__
    obj.__dict__[self.__name__] = result = self.fget(obj)
  File "/home/nicken/freelance/project/lib/python3.4/site-packages/sqlalchemy/orm/instrumentation.py", line 177, in _state_constructor
    self.dispatch.first_init(self, self.class_)
  File "/home/nicken/freelance/project/lib/python3.4/site-packages/sqlalchemy/event/attr.py", line 256, in __call__
    fn(*args, **kw)
  File "/home/nicken/freelance/project/lib/python3.4/site-packages/sqlalchemy/orm/mapper.py", line 2976, in _event_on_first_init
    configure_mappers()
  File "/home/nicken/freelance/project/lib/python3.4/site-packages/sqlalchemy/orm/mapper.py", line 2872, in configure_mappers
    mapper._post_configure_properties()
  File "/home/nicken/freelance/project/lib/python3.4/site-packages/sqlalchemy/orm/mapper.py", line 1765, in _post_configure_properties
    prop.init()
  File "/home/nicken/freelance/project/lib/python3.4/site-packages/sqlalchemy/orm/interfaces.py", line 184, in init
    self.do_init()
  File "/home/nicken/freelance/project/lib/python3.4/site-packages/sqlalchemy/orm/relationships.py", line 1652, in do_init
    self._process_dependent_arguments()
  File "/home/nicken/freelance/project/lib/python3.4/site-packages/sqlalchemy/orm/relationships.py", line 1709, in _process_dependent_arguments
    self.target = self.mapper.mapped_table
  File "/home/nicken/freelance/project/lib/python3.4/site-packages/sqlalchemy/util/langhelpers.py", line 850, in __getattr__
    return self._fallback_getattr(key)
  File "/home/nicken/freelance/project/lib/python3.4/site-packages/sqlalchemy/util/langhelpers.py", line 828, in _fallback_getattr
    raise AttributeError(key)
AttributeError: mapper

I also tried checking the code in the shell... seems to be working.

>>> from gg.app import db
>>> from gg.settings import Setting
>>> setting = Setting(name='test', description='test...', value='20', value_type='int')
>>> db.session.add(setting)
>>> db.session.commit()
>>> db.session.query(Setting).all()
[<gg.settings.Setting object at 0x7f5596d11fd0>]

回答1:


Okay, so I found a solution.

I looked at the stacktrace, opened up /home/nicken/freelance/project/lib/python3.4/site-packages/sqlalchemy/orm/relationships.py and went to line 1709.

I then put a print(self) statement just above line 1709, and that gave me more information as to where the problem was.

It turns out... elsewhere in my code, in some other model definitions, I had something like db.relationship('foo.bar.etc.SomeModel') and the reference that was being passed to db.relationship() was not valid any more, because model being referred to had been moved somewhere else.

And that's how I fixed it.



来源:https://stackoverflow.com/questions/44688346/vague-flask-sqlalchemy-error-attributeerror-mapper

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!