You are able to delete all children after their associate parent gets deleted cascadingly, but what about the opposite way? In this many-to-one relationship:
class RecipeTag(db.Model):
__tablename__ = "recipe_tags"
id = db.Column(db.Integer, primary_key=True)
recipe_id = db.Column(db.Integer, db.ForeignKey("recipes.id", ondelete="CASCADE"), nullable=False)
tag_id = db.Column(db.Integer, db.ForeignKey("tags.id", ondelete="CASCADE"), nullable=False)
parent = db.relationship("Tag", cascade="all, delete", single_parent=True, back_populates="children")
class Tag(db.Model):
__tablename__ = "tags"
id = db.Column(db.Integer, primary_key=True)
tag = db.Column(db.String, nullable=False)
children = db.relationship("RecipeTag", cascade="all, delete, delete-orphan", back_populates="parent")
The RecipeTag
will connect the Recipe
model with the Tag
model via foreign keys. However, many recipes will use the same tag, thus a Tag
can have multiple references from RecipeTag
. So when a recipe gets deleted, all its associated recipe_tags
get deleted as well automatically through cascade deletes, leaving some tags
to be childless. So it doesn't need to exist anymore.
I was thinking of querying all of the tags and pick ones out that have no children left like so:
class Tag(db.Model):
...
@staticmethod
def delete_after_no_children():
tags = Tag.query.all()
for tag in tags:
if not tag.children:
db.session.delete(tag)
db.session.commit()
This works, but I think it would be wildly inefficient. What would be the best approach to do this?