In TaxonTreeDefItem (models.py), the parent field currently presents conflicting requirements:
parent = models.ForeignKey(
'TaxonTreeDefItem',
db_column='ParentItemID',
related_name='children',
null=True,
on_delete=models.CASCADE,
)
on_delete=models.CASCADE is required to allow deletion of non-default trees.
on_delete=models.DO_NOTHING is required to allow deletion of unused ranks.
Instead of using either CASCADE or DO_NOTHING directly, replace on_delete=models.CASCADE with a new custom on_delete handler, similar to delete_with_blockers.
The custom handler should:
- Behave like CASCADE when deleting an entire tree.
- Behave like DO_NOTHING when deleting an individual rank.
For rank deletion:
- Verify that the rank is not in use (i.e., there are no nodes assigned to that rank).
- Reparent any child ranks appropriately before completing the deletion.
- There may already be existing reparenting logic that can be reused.
If the custom handler can delegate to Django's built-in CASCADE and DO_NOTHING implementations as appropriate, most of the logic may already be covered. The main remaining task is to verify that the required reparenting occurs correctly when deleting a rank.
In
TaxonTreeDefItem(models.py), the parent field currently presents conflicting requirements:on_delete=models.CASCADEis required to allow deletion of non-default trees.on_delete=models.DO_NOTHINGis required to allow deletion of unused ranks.Instead of using either
CASCADEorDO_NOTHINGdirectly, replaceon_delete=models.CASCADEwith a new custom on_delete handler, similar to delete_with_blockers.The custom handler should:
For rank deletion:
If the custom handler can delegate to Django's built-in CASCADE and DO_NOTHING implementations as appropriate, most of the logic may already be covered. The main remaining task is to verify that the required reparenting occurs correctly when deleting a rank.