在In_flush钩子中发生了“InvalidRequestError:Session已经刷新”

时间:2017-08-31 02:41:21

标签: python sqlalchemy

我想在多个模型上执行验证。下面的文档说明可以通过Session.dirty中的before_flush免费访问属性。 但是,我的代码在Session is already flushing中引发了before_flush

http://docs.sqlalchemy.org/en/rel_1_1/orm/session_events.html

经过多次尝试,我发现lazy='dynamic'是其中一个原因,但其他视图需要延迟选项。

有没有人知道什么是错的?

模型和监听器的定义

from sqlalchemy import create_engine, event, Column, Integer, String, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker

engine = create_engine('postgresql://dummy:dummy@127.0.0.1/dummy')
Base = declarative_base()


class Action(Base):
    __tablename__ = 'actions'

    id = Column(Integer, primary_key=True)
    type = Column(String(30), nullable=False)
    topic_id = Column(Integer, ForeignKey('topics.id'))
    topic = relationship('Topic', back_populates='actions')


class Topic(Base):
    __tablename__ = 'topics'

    id = Column(Integer, primary_key=True)
    name = Column(String(255), nullable=False)
    actions = relationship('Action', back_populates='topic', lazy='dynamic')


Session = sessionmaker(bind=engine)


@event.listens_for(Session, 'before_flush')
def validate_before_flush(session, flush_context, instances):
    for instance in session.dirty:
        print(instance)          # no problem(<__main__.Topic object at 0x7fa68165ecf8>)
        print(instance.name)     # no problem(modified)
        print(instance.actions)  # raise InvalidRequestError: Session is already flushing

修改模型并引发错误

session = Session()
topic = session.query(Topic).get(1)
topic.name = 'modified'
session.commit()    # Execute before_flush and raise InvalidRequestError

1 个答案:

答案 0 :(得分:0)

如果你有autoflush,那么SQLAlchemy将在从数据库查询任何内容之前尝试刷新(例如加载关系),但是当会话已经刷新时不支持刷新(例如在before_flush挂钩中) ,所以你最终得到这个错误。尝试关闭autoflush:

Session = sessionmaker(bind=engine, autoflush=False)

请注意,如果您的应用程序被编写为依赖于该行为,则关闭autoflush可能(尽管很少)破坏您的应用程序。确保你了解关闭它的含义。