gpt4 book ai didi

python - SQLAlchemy:对象列表,如果它们被删除则保留引用

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

我正在尝试实现一个面向用户的文章预览列表,即使 Article 被删除,它也会保持其大小。因此,如果列表有四个对象 [1, 2, 3, 4] 并且删除了一个对象,我希望它包含 [1, 2, None, 4]

我正在使用与 secondary 表的关系。目前,删除 ArticlePreviewList 都会删除该表中的行。我尝试过级联选项,但它们似乎直接影响相关项目,而不是 secondary 表的内容。

下面的代码片段测试了所需的行为:删除 Article 应该保留 ArticlePreviewListAssociation 中的行,但是删除 PreviewList 应该将其删除(而不是 文章)。

在下面的代码中,删除 Article 将保留 ArticlePreviewListAssociation,但 pl.articles 不会将其视为列表条目。

from db import DbSession, Base, init_db
from sqlalchemy import Column, String, Integer, ForeignKey
from sqlalchemy.orm import relationship

session = DbSession()


class Article(Base):
__tablename__ = 'articles'
id = Column(Integer, primary_key=True)
title = Column(String)


class PreviewList(Base):
__tablename__ = 'preview_lists'
id = Column(Integer, primary_key=True)
articles = relationship('Article', secondary='associations')


class ArticlePreviewListAssociation(Base):
__tablename__ = 'associations'
article_id = Column(Integer, ForeignKey('articles.id'), nullable=True)
previewlist_id = Column(Integer, ForeignKey('preview_lists.id'), primary_key=True)

article = relationship('Article')
preview_list = relationship('PreviewList')


init_db()

print(f"Creating test data")
a = Article(title="StackOverflow: 'Foo' not setting 'Bar'?")
pl = PreviewList(articles=[a])
session.add(a)
session.add(pl)
session.commit()

print(f"ArticlePreviewListAssociations: {session.query(ArticlePreviewListAssociation).all()}")

print(f"Deleting PreviewList")
session.delete(pl)
associations = session.query(ArticlePreviewListAssociation).all()
print(f"ArticlePreviewListAssociations: should be empty: {associations}")
if len(associations) > 0:
print("FAIL")

print("Reverting transaction")
session.rollback()

print("Deleting article")
session.delete(a)
articles_in_list = pl.articles
associations = session.query(ArticlePreviewListAssociation).all()
print(f"ArticlePreviewListAssociations: should not be empty: {associations}")
if len(associations) == 0:
print("FAIL")
print(f"Articles in PreviewList: should not be empty: {articles_in_list}")
if len(articles_in_list) == 0:
print("FAIL")
# desired outcome: pl.articles should be [None], not []

print("Reverting transaction")
session.rollback()

这可能归结为“如何建立多对多关系,其中 pk_A == 1 和 pk_B == NULL 在 A 的列表中包含 None ?”

最佳答案

给出的例子似乎假设相关文章的顺序被保留,即使在删除时也是如此。有多种方法,例如 Ordering List扩展,但首先解决保留与已删除文章的关联的问题更容易。这似乎是 association object 的用例和 proxy .

Article 类获得了新的关系,以便在 session 中进行级联删除。默认 ORM-level cascading行为是设置外键为NULL,但是如果没有加载相关的关联对象,我们想让DB去做,所以使用了passive_deletes=True:

class Article(Base):
__tablename__ = 'articles'

id = Column(Integer, primary_key=True)
title = Column(String)

previewlist_associations = relationship(
'ArticlePreviewListAssociation', back_populates='article',
passive_deletes=True)

代替多对多关系 PreviewList 使用关联对象模式,以及替代多对多关系的关联代理。这次级联有点不同,因为关联对象应该被删除,如果父 PreviewList 被删除:

class PreviewList(Base):
__tablename__ = 'preview_lists'

id = Column(Integer, primary_key=True)

article_associations = relationship(
'ArticlePreviewListAssociation', back_populates='preview_list',
cascade='all, delete-orphan', passive_deletes=True)

articles = association_proxy(
'article_associations', 'article',
creator=lambda a: ArticlePreviewListAssociation(article=a))

最初,关联对象使用 previewlist_id 作为主键,但后来 PreviewList 只能包含一个 Article。代理键解决了这个问题。外键配置包括数据库级联。这些是使用被动删除的原因:

class ArticlePreviewListAssociation(Base):
__tablename__ = 'associations'

id = Column(Integer, primary_key=True)
article_id = Column(
Integer, ForeignKey('articles.id', ondelete='SET NULL'))
previewlist_id = Column(
Integer, ForeignKey('preview_lists.id', ondelete='CASCADE'),
nullable=False)

# Using a unique constraint on a nullable column is a bit ugly, but
# at least this prevents inserting an Article multiple times to a
# PreviewList.
__table_args__ = (UniqueConstraint(article_id, previewlist_id), )

article = relationship(
'Article', back_populates='previewlist_associations')
preview_list = relationship(
'PreviewList', back_populates='article_associations')

进行这些更改后,不会打印“FAIL”。

关于python - SQLAlchemy:对象列表,如果它们被删除则保留引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49621202/

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