I have a situation where upon deletion of a Key (Parent), I want to delete all its Values (children), and the related rows in a MTM association between Children and Foo. The models are as follows (some attribs removed):
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')
And the association_table is just a classic FK<-->FK table:
Table("association_table",
Model.metadata,
Column("foo.id", Integer, ForeignKey("foos.id"),
Column("value.id", Integer, ForeignKey("values.id"),)
With this setup, using postgres, when I'm trying to delete a Key, I get the following:
(psycopg2.errors.ForeignKeyViolation) update or delete on table "values" violates foreign key constraint "association_table_value_id_fkey" on table "association_table"
Now, reading through the Documentation I've tried the examples there which mostly seem to say put an ondelete="CASCADE" on your association table. However this results in the same issue.
Is there a way I can do what I want, e.g. "unlink" the foo objects from the MTM table (without deleting them)?
If you are using postgres, it would be useful to know wich version you are running. There are some similar issues which might be related if you are using a version lower than 12.2.
However, from your code, where did you try ondelete="CASCADE"?
This is working for me:
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'
)
Then I can run (using 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>]
I tried after without ondelete="CASCADE" and I could reproduce your error.
ForeignKeyViolation: update or delete on table "values" violates foreign key constraint "association_table_value.id_fkey" on table "association_table"
From your code, for future readers, note the following:
__tablename__, I suppose from your code is set adding 's'.) on Column("foo.id").If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With