我面对错误,我无法理解的女巫感:
我写模型:
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255))
class UserFile(db.Model):
__tablename__ = 'user_files'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255))
author_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
author = db.relationship(User, foreign_keys=[author_id])
删除UserFile实例时,我需要执行许多其他步骤。
直接删除UserFile实例后,我可以做任何我想做的事。删除用户实例时出现问题。在这种情况下,我需要删除与该用户关联的所有UserFile实例。但是我不能使用级联删除,因为我需要为每个UserFile执行其他操作。
我尝试使用SQLAlchemy'before_delete'事件,但是我收到一个错误,因为它在删除后已经在运行,尽管它被称为'before'。我是通过将消息的输出添加到控制台来看到此消息的,直到收到错误后才在控制台中看到此消息。
然后我尝试使用FLASK-sqlalchemy信号。我做到了:
从flask_sqlalchemy导入before_models_committed
@before_models_committed.connect_via(app)
def delete_all_user_folders_after_delete(sender, changes):
for obj, operation in changes:
if isinstance(obj, User) and operation == 'delete':
print('files: ', UserFile.query.filter_by(author_id=obj.id, parent_id=None).all())
for item in UserFile.query.filter_by(author_id=obj.id,
parent_id=None).all():
print(item)
delete_file(item, True)
并在网上出现错误:
print ('files: ', UserFile.query.filter_by(author_id=obj.id, parent_id=None).all())
此错误的原因是什么?如何在删除用户之前正确预删除所有用户文件?
错误说明:
sqlalchemy.exc.IntegrityError: (raised as a result of Query-invoked autoflush; consider using a session.no_autoflush block if this flush is occurring prematurely) (psycopg2.IntegrityError) update or delete on table "users" violates foreign key constraint "user_files_author_id_fkey" on table "user_files"
DETAIL: Key (id)=(2) is still referenced from table "user_files".
答案 0 :(得分:0)
在delete_all_user_folders_after_delete()
中执行的查询会导致autoflush,这会在完成手动清理之前过早清除删除内容。 PostgreSQL中的默认引用操作是NO ACTION
,即"means that if any referencing rows still exist when the constraint is checked, an error is raised"。似乎您没有推迟相关的约束,因此将立即对其进行检查。
您也许可以尝试错误消息中提出的解决方案:
@before_models_committed.connect_via(app)
def delete_all_user_folders_after_delete(sender, changes):
for obj, operation in changes:
if isinstance(obj, User) and operation == 'delete':
with db.session.no_autoflush:
fs = UserFile.query.filter_by(author_id=obj.id, parent_id=None).all()
print('files: ', fs)
for item in fs:
print(item)
# If this queries the DB, remember to disable autoflush again
delete_file(item, True)