如何从 SqlAlchemy 中的多对多集合中删除所有项目?

Posted

技术标签:

【中文标题】如何从 SqlAlchemy 中的多对多集合中删除所有项目?【英文标题】:How to remove all items from many-to-many collection in SqlAlchemy? 【发布时间】:2011-12-14 21:23:18 【问题描述】:

当我需要从声明性 ORM 多对多关系中删除对象时,我应该这样做:

blogpost.tags.remove(tag)

嗯。如果我需要清除所有这些关系(不仅仅是一个),我应该怎么做?典型情况:我想为我的博文设置一个新的标签列表。所以我需要...:

    删除该博文和标签之间的所有现有关系。 设置新关系并在不存在时创建新标签。

当然,可能有更好的方法来做到这一点。在这种情况下,请告诉我。

【问题讨论】:

【参考方案1】:

这是清除列表的标准 Python 习语——分配给“整个列表”切片:

blogpost.tags[:] = []

您可能希望直接分配新的标签集,而不是空列表。

blogpost.tags[:] = new_tags

SQLAlchemy 的关系是instrumented attributes,这意味着它们保留了列表(或集合、字典等)的接口,但任何更改都会反映在数据库中。这意味着您可以对列表执行的任何操作都可以通过关系实现,而 SQLA 透明地侦听更改并相应地更新数据库。

【讨论】:

或者换一种说法:SQLAlchemy 很棒。 为什么不只是blogpost.tags = new_tags? (不带 [:]) 当我现在尝试这个时(2014 年 12 月,SQLAlchemy 0.9)我得到“TypeError: 'AppenderBaseQuery' 对象不支持项目分配。” 我花了很长时间在谷歌搜索“SQLAlchemy 如何替换所有关系元素”。在这里评论,希望有助于简化搜索。 @Devi 这不起作用。您将用新类型(列表)替换 sqla Collection 对象 随着图书馆在版本/年中的演变,许多事情必须发生变化,并且接受和一旦工作的答案现在可能不起作用。 Q 和 A 中的版本最好是精确的。【参考方案2】:

确认Two-Bit Alchemist 报告的内容。

blogpost.tags[:] = new_tags

会抱怨

TypeError: 'AppenderBaseQuery' object does not support item assignment

但是

blogpost.tags = new_tags

似乎工作正常。

【讨论】:

这不会将任何内容保存到数据库中,这意味着设置为空列表不会清除记录 @kevlarr 这确实有效,因为blogpost 对象的tags 字段也被检测;当您为其分配一个空列表时,该空列表将替换为一个空的sqlalchemy.orm.dynamic.AppenderBaseQuery 对象。 @Tom 如果是版本问题,我会很好奇,因为我已经尝试过,结果与您报告的结果不同。不过,我无法再访问代码,所以不确定我使用的是什么版本(在我发表评论时它应该是最新的)。您确定空列表的分配实际上删除了数据库记录

以上是关于如何从 SqlAlchemy 中的多对多集合中删除所有项目?的主要内容,如果未能解决你的问题,请参考以下文章

sqlalchemy中的多对多自引用关系

当对集合进行 get 调用时,Hibernate 会删除延迟加载的多对多集合

SQLAlchemy如何反映多对多关系

Remove() 不适用于实体框架中的多对多关系

python中flask和sqlalchemy的多对多

SQLAlchemy 使用关联配置与自我的多对多关系