I’ve been playing with some ideas for automating referential integrity with models, and wanted to share in case someone else has a use for it, or in case it sparks some ideas.
I wrote a couple of simple functions that can be used to keep single link columns intact (either by deleting the rows they link from, or by preventing the deletion…this could be extended to setting the linked column to None as well).
def restrict_on_delete(row, table, column):
params = {column: row}
results = table.search(**params)
if results:
raise ChildExists("Child row found, cannot delete parent row")
def cascade_on_delete(row, table, column):
params = {column: row}
results = table.search(**params)
for result in results:
result.delete()
And then in a model I’d use those in the _do_delete
method:
class Category(app_tables.categories.Row, buffered=True, client_updatable=True, client_deletable=True):
def _do_delete(self, from_client):
cascade_on_delete(self, app_tables.profile, 'category')
# restrict_on_delete(self, app_tables.profile, 'category')
super()._do_delete(from_client)
I’m not super happy with the fact that it’s the Category model that knows about what links to it, but that seems the most straightforward way of handling it.
ChildExists is a custom Exception I registered with Anvil, ala: Handling exception coming from the server/uplink modules - #3
There’d need to be a separate set of functions to handle multiple link columns, but the same approach could be used.
Caution! If you delete something that cascade deletes something else that’s already in a search result somewhere, you’ll get a deleted row exception if you try to save changes to it. That’s to be expected.