gpt4 book ai didi

python - SQLAlchemy 级联删除到多对多表

转载 作者:行者123 更新时间:2023-12-05 06:05:15 30 4
gpt4 key购买 nike

我有一种情况,我想在删除键(父)时删除它的所有值(子),以及子和 Foo 之间的 MTM 关联中的相关行。模型如下(去掉了部分属性):


class Key(Model):
...
values = relationship('Value', back_populates='key', cascade='all, delete-orphan')

class Value(Model):

value = Column(Text, nullable=False)
key = relationship("Key", back_populates="values")
key_id = Column(Integer, ForeignKey("keys.id"))


class Foo(Model):

...
taglist = db.relationship("Value",
order_by="desc(Value.created)",
secondary=association_table,
lazy='dynamic')

association_table 只是一个经典的 FK<-->FK 表:

Table("association_table", 
Model.metadata,
Column("foo.id", Integer, ForeignKey("foos.id"),
Column("value.id", Integer, ForeignKey("values.id"),)

通过此设置,使用 postgres,当我尝试删除 key 时,我得到以下信息:(psycopg2.errors.ForeignKeyViolation) 更新或删除表“values”违反了表“association_table”上的外键约束“association_table_value_id_fkey”

现在,阅读 https://docs.sqlalchemy.org/en/14/orm/basic_relationships.html#relationships-many-to-many-deletion文档我已经尝试了那里的示例,这些示例大多是说在您的关联表上放置一个 ondelete="CASCADE",但是这会导致同样的问题。

有没有办法让我做我想做的事,例如从 MTM 表中“取消链接”foo 对象(不删除它们)?

在此先感谢您的帮助

最佳答案

如果您正在使用 postgres,了解您正在运行的版本会很有用。有一些similar issues如果您使用的版本低于 12.2,这可能是相关的。

但是,从您的代码中,您在哪里尝试了 ondelete="CASCADE"?这对我有用:

association = Table("association_table", 
PkModel.metadata,
Column("foo.id", ForeignKey("foos.id")),
Column("value.id", ForeignKey("values.id", ondelete="CASCADE"))
)


class Key(PkModel):
__tablename__ = "keys"
values = relationship('Value', back_populates='key', cascade='all, delete-orphan')


class Value(PkModel):
__tablename__ = "values"
created = Column(DateTime, nullable=False, default=dt.utcnow)
value = Column(Text, nullable=False)
key = relationship("Key", back_populates="values")
key_id = Column(ForeignKey("keys.id"))


class Foo(PkModel):
__tablename__ = "foos"
taglist = relationship(
"Value",
order_by="desc(Value.created)",
secondary=association,
lazy='dynamic'
)

然后我可以运行(使用 postgres 12.2):

>>>f1 = models.Foo.create()
>>>f1.taglist.all()
[]
>>>k1 = models.Key.create(values=[models.Value(value="bar")])
>>>k1.values
[<Value 54a7c726-acc9...b8c87e590>]
>>>models.Value.query.all()
[<Value 54a7c726-acc9...b8c87e590>]

>>>f1.update(taglist=[v1])
<Foo 8a1b6701-384e-4bc0-8e29-9ac4e64a4fdf>
>>>f1 = models.Foo.query.all()[0]
>>>f1.taglist.all()
[<Value 54a7c726-acc9...b8c87e590>]

>>>k1.delete()
None
>>>f1.taglist.all()
[]

>>>models.Key.query.all()
[]
>>>models.Value.query.all()
[]
>>>models.Foo.query.all()
[<Foo 8a1b6701-384e-4...4e64a4fdf>]

我在没有 ondelete="CASCADE" 的情况下尝试过,我可以重现您的错误。

ForeignKeyViolation: update or delete on table "values" violates foreign key constraint "association_table_value.id_fkey" on table "association_table"

对于您的代码,对于 future 的读者,请注意以下几点:

  • 缺少 __tablename__,我想根据您的代码设置添加“s”。
  • 在关联表上,在 Column("foo.id") 上缺少一个 )
  • Value 没有名为“created”的映射列。

关于python - SQLAlchemy 级联删除到多对多表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66063035/

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