【发布时间】:2017-09-14 19:26:06
【问题描述】:
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
class Paper(db.Model):
__tablename__ = 'papers'
id = db.Column(db.Integer, primary_key=True)
reviewers = db.relationship('User', secondary=paper_reviewer,
backref=db.backref('papers_reviewed',
lazy='dynamic'),
lazy='dynamic')
paper_reviewer = db.Table('paper_reviewer',
db.Column('user_id', db.Integer,
db.ForeignKey('users.id'),
primary_key=True),
db.Column('paper_id', db.Integer,
db.ForeignKey('papers.id'),
primary_key=True)
)
@event.listens_for(Paper.reviewers, 'append')
def paper_reviewers_append(target, value, initiator):
# db operation on other tables
# target is paper obj
print target.reviewers.all() # or other operation
paper.reviewers.append(usr)
db.session.add(paper)
db.session.commit()
侦听器在paper.reviewers.append(usr) 执行之前被触发。 append 的执行对 paper_reviewer 表进行了两次插入。第二个原因是IntegrityError: UNIQUE constraint failed。
我在监听器中尝试了不同的操作。如果该操作触发了任何查询,则会在执行 commit() 时引发 IntegrityError。
【问题讨论】:
-
您必须提供 [mvce]。
# db operation on other tables不足以说明问题。 -
@univerio 我在描述中已经提到:如果操作触发了任何查询,则会在执行 commit() 时引发 IntegrityError。调用哪个表无关紧要。
-
我知道你已经描述了你在做什么。我要的是一个可以运行的具体示例。如果是任何查询,则输入您想要的任何查询。想想我需要采取哪些步骤来重现您的问题;我需要添加缺少的
User模型,然后解释db operation on other tables的意思,最后,如果一切正常,再猜猜我是否正确解释了db operation on other tables。提供一个完整的例子将消除其他变量。抱歉,我之前弄乱了链接:minimal reproducible example -
@univerio 谢谢回复。我没想到你会尝试运行代码。类似的问题已经发布在 google group 上。解决方案是“您的侦听器中可能发生了自动刷新,因此请使用“with session.no_autoflush”:docs.sqlalchemy.org/en/latest/orm/…“
-
通用的“禁用自动刷新”似乎是个坏建议。了解 autoflush 实际上是什么以及它发生的原因(查询可能会观察到陈旧状态,如果会话有修改),与实际正在执行的操作相关,这将有更多帮助,此处仍未显示。
标签: python flask sqlalchemy flask-sqlalchemy