#python #sqlalchemy #pyramid
#python #sqlalchemy #пирамида
Вопрос:
Когда я запускаю initializedb.py
скрипт, мои таблицы создаются нормально, но когда я пытаюсь вставить какие-либо данные, я получаю следующую ошибку:
TypeError: unbound method after_attach() must be called with ZopeTransactionExtension instance as first argument (got Session instance instead)
Почему я получаю эту ошибку? Я попытался найти ошибку в Google, но единственный пример, связанный со мной, который я нашел, был связан с неправильным запросом.
Моя структура пакета и соответствующие разделы кода следующие:
В моем приложении Pyramid вместо определения всех моделей в models.py
файле я создал отдельный пакет под названием models и поместил туда все мои классы моделей.
В принципе, у меня есть
myapp/
models/
__init__.py
meta.py
school.py
__init__.py
Мой основной __init__.py
имеет:
from myapp.models.meta import (
DBSession,
Base,
)
Аналогично, __init__.py
файл внутри models
имеет:
from .meta import DBSession
from .school import School
meta.py
внутри models
есть:
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import (
scoped_session,
sessionmaker,
)
from zope.sqlalchemy import ZopeTransactionExtension
Base = declarative_base()
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension))
Файл модели school.py
имеет:
from .meta import (
Base,
get_prefix,
)
class School(Base):
""" The SQLAlchemy declarative model class for a School object. """
__tablename__ = 'schools'
id = Column(Integer, primary_key=True)
school_code = Column(String(10))
И, наконец, scripts/initializedb.py
файл имеет:
from myapp.models.meta import (
Base,
DBSession,
)
from myapp.models import (
School,
)
def main(argv=sys.argv):
if len(argv) < 2:
usage(argv)
config_uri = argv[1]
options = parse_vars(argv[2:])
setup_logging(config_uri)
settings = get_appsettings(config_uri, options=options)
engine = engine_from_config(settings, 'sqlalchemy.')
DBSession.configure(bind=engine)
Base.metadata.create_all(engine)
with transaction.manager:
demo_school = School(school_code="SC-123")
DBSession.add(demo_school)
Редактировать:
Полная трассировка выглядит следующим образом:
2014-06-22 20:18:31,577 INFO [sqlalchemy.engine.base.Engine][MainThread] SHOW VARIABLES LIKE 'sql_mode'
2014-06-22 20:18:31,577 INFO [sqlalchemy.engine.base.Engine][MainThread] ()
2014-06-22 20:18:31,585 DEBUG [sqlalchemy.engine.base.Engine][MainThread] Col ('Variable_name', 'Value')
2014-06-22 20:18:31,586 DEBUG [sqlalchemy.engine.base.Engine][MainThread] Row ('sql_mode', '')
2014-06-22 20:18:31,586 INFO [sqlalchemy.engine.base.Engine][MainThread] SELECT DATABASE()
2014-06-22 20:18:31,586 INFO [sqlalchemy.engine.base.Engine][MainThread] ()
2014-06-22 20:18:31,587 DEBUG [sqlalchemy.engine.base.Engine][MainThread] Col ('DATABASE()',)
2014-06-22 20:18:31,587 DEBUG [sqlalchemy.engine.base.Engine][MainThread] Row ('myapp',)
2014-06-22 20:18:31,588 INFO [sqlalchemy.engine.base.Engine][MainThread] show collation where `Charset` = 'utf8' and `Collation` = 'utf8_bin'
2014-06-22 20:18:31,588 INFO [sqlalchemy.engine.base.Engine][MainThread] ()
2014-06-22 20:18:31,590 DEBUG [sqlalchemy.engine.base.Engine][MainThread] Col ('Collation', 'Charset', 'Id', 'Default', 'Compiled', 'Sortlen')
2014-06-22 20:18:31,591 DEBUG [sqlalchemy.engine.base.Engine][MainThread] Row ('utf8_bin', 'utf8', 83L, '', 'Yes', 1L)
2014-06-22 20:18:31,592 INFO [sqlalchemy.engine.base.Engine][MainThread] SELECT CAST('test plain returns' AS CHAR(60)) AS anon_1
2014-06-22 20:18:31,592 INFO [sqlalchemy.engine.base.Engine][MainThread] ()
2014-06-22 20:18:31,593 INFO [sqlalchemy.engine.base.Engine][MainThread] SELECT CAST('test unicode returns' AS CHAR(60)) AS anon_1
2014-06-22 20:18:31,593 INFO [sqlalchemy.engine.base.Engine][MainThread] ()
2014-06-22 20:18:31,594 INFO [sqlalchemy.engine.base.Engine][MainThread] SELECT CAST('test collated returns' AS CHAR CHARACTER SET utf8) COLLATE utf8_bin AS anon_1
2014-06-22 20:18:31,595 INFO [sqlalchemy.engine.base.Engine][MainThread] ()
2014-06-22 20:18:31,596 INFO [sqlalchemy.engine.base.Engine][MainThread] DESCRIBE `a3fhs32g_schools`
2014-06-22 20:18:31,597 INFO [sqlalchemy.engine.base.Engine][MainThread] ()
2014-06-22 20:18:31,598 DEBUG [sqlalchemy.engine.base.Engine][MainThread] Col ('Field', 'Type', 'Null', 'Key', 'Default', 'Extra')
2014-06-22 20:18:31,598 DEBUG [sqlalchemy.engine.base.Engine][MainThread] Row ('id', 'int(11)', 'NO', 'PRI', None, 'auto_increment')
2014-06-22 20:18:31,598 INFO [sqlalchemy.engine.base.Engine][MainThread] DESCRIBE `a3fhs32g_students`
2014-06-22 20:18:31,598 INFO [sqlalchemy.engine.base.Engine][MainThread] ()
2014-06-22 20:18:31,599 DEBUG [sqlalchemy.engine.base.Engine][MainThread] Col ('Field', 'Type', 'Null', 'Key', 'Default', 'Extra')
2014-06-22 20:18:31,599 DEBUG [sqlalchemy.engine.base.Engine][MainThread] Row ('id', 'int(11)', 'NO', 'PRI', None, 'auto_increment')
Traceback (most recent call last):
File "../bin/initialize_myapp_db", line 9, in <module>
load_entry_point('myapp==0.0', 'console_scripts', 'initialize_myapp_db')()
File "/var/www/html/myapp/app/myapp/myapp/myapp/scripts/initializedb.py", line 44, in main
DBSession.add(model)
File "/var/www/html/myapp/app/myapp/local/lib/python2.7/site-packages/SQLAlchemy-0.9.4-py2.7-linux-i686.egg/sqlalchemy/orm/scoping.py", line 149, in do
return getattr(self.registry(), name)(*args, **kwargs)
File "/var/www/html/myapp/app/myapp/local/lib/python2.7/site-packages/SQLAlchemy-0.9.4-py2.7-linux-i686.egg/sqlalchemy/orm/session.py", line 1478, in add
self._save_or_update_state(state)
File "/var/www/html/myapp/app/myapp/local/lib/python2.7/site-packages/SQLAlchemy-0.9.4-py2.7-linux-i686.egg/sqlalchemy/orm/session.py", line 1490, in _save_or_update_state
self._save_or_update_impl(state)
File "/var/www/html/myapp/app/myapp/local/lib/python2.7/site-packages/SQLAlchemy-0.9.4-py2.7-linux-i686.egg/sqlalchemy/orm/session.py", line 1744, in _save_or_update_impl
self._save_impl(state)
File "/var/www/html/myapp/app/myapp/local/lib/python2.7/site-packages/SQLAlchemy-0.9.4-py2.7-linux-i686.egg/sqlalchemy/orm/session.py", line 1716, in _save_impl
self._attach(state)
File "/var/www/html/myapp/app/myapp/local/lib/python2.7/site-packages/SQLAlchemy-0.9.4-py2.7-linux-i686.egg/sqlalchemy/orm/session.py", line 1844, in _attach
self.dispatch.after_attach(self, state.obj())
File "/var/www/html/myapp/app/myapp/local/lib/python2.7/site-packages/SQLAlchemy-0.9.4-py2.7-linux-i686.egg/sqlalchemy/event/attr.py", line 257, in __call__
fn(*args, **kw)
TypeError: unbound method after_attach() must be called with ZopeTransactionExtension instance as first argument (got Session instance instead)
Ответ №1:
DBSession
в вашем случае это объект scoped_session . Чтобы получить фактический сеанс, вы должны вызвать его (что запускает вызов базовой фабрики сеансов).
def main(argv=sys.argv):
...
DBSession.configure(bind=engine)
Base.metadata.create_all(engine)
session = DBSession()
....
session.add(model)
Ответ №2:
Ошибка означает, что вам нужен экземпляр DBSession, но класс. Я действительно не знаю пирамиду, но, возможно DBSession configure
, вызов возвращает экземпляр? Если это так, вы должны зафиксировать возвращаемое значение и вызвать add
его.
Комментарии:
1. Большое спасибо! Я только что попробовал то, что вы сказали, но
DBSession.configure()
не возвращает ничего.2. Можете ли вы опубликовать полную обратную трассировку?
3. Я только что отредактировал вопрос, чтобы добавить полную обратную трассировку.