gpt4 book ai didi

python - 在 SQLAlchemy 中删除父项后删除子项

转载 作者:太空宇宙 更新时间:2023-11-04 01:32:45 25 4
gpt4 key购买 nike

我的问题如下:

我在 SQLAlchemy 中通过多对多关系链接了两个模型 EntryTag。现在我想在删除 Entry 之后删除没有任何对应 Entry 的每个 Tag

举例说明我想要什么:

  • 条目 1 带有标签 pythonjava

  • 条目 2 带有标签 pythonc++

通过这两个条目,数据库包含标签pythonjavac++。如果我现在删除 Entry 2,我希望 SQLAlchemy 自动从数据库中删除 c++ 标记。是否可以在 Entry 模型本身中定义此行为,或者是否有更优雅的方式?

谢谢。

最佳答案

这个问题刚才在这里被问到:Setting delete-orphan on SQLAlchemy relationship causes AssertionError: This AttributeImpl is not configured to track parents

这就是“多对多孤儿”问题。 jadkik94 很接近,因为您应该使用事件来捕获它,但我尝试建议不要在映射器事件中使用 Session,尽管它在这种情况下有效。

下面,我从另一个 SO 问题中逐字回答,并将“角色”一词替换为“条目”:

from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import event
from sqlalchemy.orm import attributes

Base= declarative_base()

tagging = Table('tagging',Base.metadata,
Column('tag_id', Integer, ForeignKey('tag.id', ondelete='cascade'), primary_key=True),
Column('entry_id', Integer, ForeignKey('entry.id', ondelete='cascade'), primary_key=True)
)

class Tag(Base):

__tablename__ = 'tag'
id = Column(Integer, primary_key=True)
name = Column(String(100), unique=True, nullable=False)

def __init__(self, name=None):
self.name = name

class Entry(Base):
__tablename__ = 'entry'

id = Column(Integer, primary_key=True)
tag_names = association_proxy('tags', 'name')

tags = relationship('Tag',
secondary=tagging,
backref='entries')

@event.listens_for(Session, 'after_flush')
def delete_tag_orphans(session, ctx):
# optional: look through Session state to see if we want
# to emit a DELETE for orphan Tags
flag = False

for instance in session.dirty:
if isinstance(instance, Entry) and \
attributes.get_history(instance, 'tags').deleted:
flag = True
break
for instance in session.deleted:
if isinstance(instance, Entry):
flag = True
break

# emit a DELETE for all orphan Tags. This is safe to emit
# regardless of "flag", if a less verbose approach is
# desired.
if flag:
session.query(Tag).\
filter(~Tag.entries.any()).\
delete(synchronize_session=False)


e = create_engine("sqlite://", echo=True)

Base.metadata.create_all(e)

s = Session(e)

r1 = Entry()
r2 = Entry()
r3 = Entry()
t1, t2, t3, t4 = Tag("t1"), Tag("t2"), Tag("t3"), Tag("t4")

r1.tags.extend([t1, t2])
r2.tags.extend([t2, t3])
r3.tags.extend([t4])
s.add_all([r1, r2, r3])

assert s.query(Tag).count() == 4

r2.tags.remove(t2)

assert s.query(Tag).count() == 4

r1.tags.remove(t2)

assert s.query(Tag).count() == 3

r1.tags.remove(t1)

assert s.query(Tag).count() == 2

两个几乎相同的 SO 问题使它成为手头上的东西,所以我将它添加到维基中 http://www.sqlalchemy.org/trac/wiki/UsageRecipes/ManyToManyOrphan .

关于python - 在 SQLAlchemy 中删除父项后删除子项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12653824/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com