sqlalchemy listens_for 在 table 完全创建之前发生
sqlalchemy listens_for happening before table is fully created
我注意到 sqlalchemy 的 listens_for 装饰器在 table 完全创建之前启动,至少在我的代码中是这样。我应该怎么做才能确保它在之后开始。如果您需要更多代码,请告诉我。
错误是
Exception has occurred: ProgrammingError
(psycopg2.errors.UndefinedTable) relation "organization" does not exist
我的数据库会话是在 database.py
中创建的
engine = sqlalchemy.create_engine(current_app.config['DATABASE_URL'])
db_session = scoped_session(sessionmaker(
autocommit=False,
autoflush=False,
bind=engine))
Base = declarative_base(bind=engine)
Base.query = db_session.query_property()
def init_db():
from . import models
Base.metadata.drop_all(bind=engine)
Base.metadata.create_all(bind=engine)
@current_app.teardown_appcontext
def shutdown_session(exception=None):
db_session.remove()
我的模型是在 models.py
中创建的
class BaseModel(Base):
__abstract__ = True
created_on = Column(DateTime, default=func.now())
updated_on = Column(DateTime, default=func.now(), onupdate=func.now())
class BaseModelId(BaseModel):
__abstract__ = True
id = Column(Integer, primary_key=True)
class Organization(BaseModelId):
__tablename__ = 'organization'
name = Column(String(128))
装饰器问题listens_for
@event.listens_for(Organization.__table__, 'after_create')
def insert_organizations(*args, **kwargs):
db_session.add(Organization(
name='organization',
))
db_session.commit()
如果我进行一些登录,事件会在 Base.metadata.create_all(bind=engine)
完成之前被调用
如果我使用 Timer
让一两秒过去,错误消息就会消失
def insert_organizations(*args, **kwargs):
Timer(2, _insert_organizations).start()
def _insert_organizations():
db_session.add(Organization(
name='organization',
))
db_session.commit()
这里的问题是 Base.metadata.create_all
使用的连接与 db_session
不同,因此当 commit()
在事件侦听器中调用时 create_all
的事务尚未完成提交。
事件侦听器同时接收 table 对象和 create_all
使用的连接,因此我们可以使用这些对象来插入记录而不是会话。
@sa.event.listens_for(Organization.__table__, 'after_create')
def insert_organizations(tbl, conn, **kw):
conn.execute(tbl.insert().values(name='organisation'))
我注意到 sqlalchemy 的 listens_for 装饰器在 table 完全创建之前启动,至少在我的代码中是这样。我应该怎么做才能确保它在之后开始。如果您需要更多代码,请告诉我。
错误是
Exception has occurred: ProgrammingError (psycopg2.errors.UndefinedTable) relation "organization" does not exist
我的数据库会话是在 database.py
中创建的engine = sqlalchemy.create_engine(current_app.config['DATABASE_URL'])
db_session = scoped_session(sessionmaker(
autocommit=False,
autoflush=False,
bind=engine))
Base = declarative_base(bind=engine)
Base.query = db_session.query_property()
def init_db():
from . import models
Base.metadata.drop_all(bind=engine)
Base.metadata.create_all(bind=engine)
@current_app.teardown_appcontext
def shutdown_session(exception=None):
db_session.remove()
我的模型是在 models.py
中创建的class BaseModel(Base):
__abstract__ = True
created_on = Column(DateTime, default=func.now())
updated_on = Column(DateTime, default=func.now(), onupdate=func.now())
class BaseModelId(BaseModel):
__abstract__ = True
id = Column(Integer, primary_key=True)
class Organization(BaseModelId):
__tablename__ = 'organization'
name = Column(String(128))
装饰器问题listens_for
@event.listens_for(Organization.__table__, 'after_create')
def insert_organizations(*args, **kwargs):
db_session.add(Organization(
name='organization',
))
db_session.commit()
如果我进行一些登录,事件会在 Base.metadata.create_all(bind=engine)
完成之前被调用
如果我使用 Timer
让一两秒过去,错误消息就会消失def insert_organizations(*args, **kwargs):
Timer(2, _insert_organizations).start()
def _insert_organizations():
db_session.add(Organization(
name='organization',
))
db_session.commit()
这里的问题是 Base.metadata.create_all
使用的连接与 db_session
不同,因此当 commit()
在事件侦听器中调用时 create_all
的事务尚未完成提交。
事件侦听器同时接收 table 对象和 create_all
使用的连接,因此我们可以使用这些对象来插入记录而不是会话。
@sa.event.listens_for(Organization.__table__, 'after_create')
def insert_organizations(tbl, conn, **kw):
conn.execute(tbl.insert().values(name='organisation'))