数据库值在 session.commit() 之后恢复



我遇到了一个问题,在调用session.commit((后,某些数据似乎恢复到原始值。 这是我当前正在运行的代码:

def delete_source(source_id):
source = Source.query.get_or_404(source_id)
tasks = Task.query.all()
log.info_print(f"source_id = {source_id}")
log.info_print(f"Before commit [1]: {tasks}")
for task in tasks:
if source_id in task.source:
task.source.remove(source_id)
log.info_print(f"Before commit [2]: {tasks}")
db.session.delete(source)   
db.session.commit()
log.info_print(f"After commit [1]: {tasks}")

输出是这样的:

source_id = 42
Before commit [1]: [Task('ID: 1', 'Source: [42, 15]')]
Before commit [2]: [Task('ID: 1', 'Source: [15]')]
After commit [1]: [Task('ID: 1', 'Source: [42, 15]')]

关于目标的说明在这里... 调用此路由时,它会使用db.session.delete(source)从源数据库表中删除具有source_id的项目,但这仍然将source_id保留在 Task 表中(特别是在 Source 数组中(,因此这就是为什么我有for task in tasks循环将其从源数组中删除。

它已成功从数组中删除值,如Before commit [2]日志条目所示。但后来由于某种原因,它又回来了。但是删除的源没有(当然,它不应该这样做!

期待一些建议!谢谢!

我浏览了文档,但我对 sqlalchemy 不太熟悉,所以我没有找到太多。一种理论认为,tasks = Task.query.all()创建的Query对象检测到您已向数据库提交新的更改,并在下次使用它时自动重新计算tasks- 在这种情况下,当您在提交后日志消息中打印它时。然后,从数据库返回的这个新生成的tasks仍将删除的源存储在其源数组中。

我遇到的一个用于Session对象的参数称为expire_on_commitSession.commit()的文档说(强调我的(:

默认情况下,会话还会在事务提交后使所有 ORM 管理的属性上的所有数据库加载状态过期。这样,后续操作就会从数据库加载最新数据。可以使用会话管理器或会话构造函数的 expire_on_commit=False 选项禁用此行为。

我不确定引用Query结果是否被视为"后续交易",但我不可能。就像我说的,我对sqlalchemy了解不多,所以这个标志实际上可能与这种特殊情况无关,而且重新计算tasks的整个理论可能完全偏离了基础,但我想我会分享我的发现,以防它被证明是有帮助的。

您可以在此处阅读有关会话和提交方法的更多信息:https://docs.sqlalchemy.org/en/13/orm/session_api.html#sqlalchemy.orm.session.Session.commit

我遇到了同样的问题,并为自己找到了解决方案。我在研究过程中发现了这个问题,并想回答它,因为它仍然没有真正得到答案。在这里:https://stackoverflow.com/a/72861174/17555759 是我的帖子和我的答案。

我相信您需要做的是手动重新创建多对多密钥。以下是我用来解决此问题的代码:

UserPost.query.filter_by(post_id=post_id).delete()
for a_id in author_ids:
user = User.query.get(a_id)
db.session.add(UserPost(user_id=a_id,post_id=post_id))

在这里,我删除了定义用户和帖子模型之间关系的用户发布(多对多关系表(条目。然后,我使用要关联的帖子和用户的 ID 手动添加了一个新条目。SQLAlchemy 似乎不会自动级联这样的事情。

我认为从根本上发生的事情是,当我们只删除任务模型中的关系条目时,我们将数据库置于不一致的状态。当调用 db.session.commit(( 时,数据将过期并刷新,这反过来又会导致 M2M 模型中的数据再次重新应用于各个任务,而不是跨关系模型保留我们对任务模型的更改。

最新更新