问题
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