"""Signal handlers for the submissions app. The cleanup story (plan.md ยง7.6): when a `Submission` row is deleted -- manually, via `cleanup_stale`, or for any other reason -- the uploaded `.stl` file must also be unlinked from `MEDIA_ROOT`. Django's `FileField` does NOT do this automatically (the behaviour was removed in 1.3, ages ago), so we wire a `post_delete` signal to take care of it. """ from __future__ import annotations from django.db.models.signals import post_delete from django.dispatch import receiver from .models import Submission @receiver(post_delete, sender=Submission) def unlink_stl_file_on_delete(sender, instance: Submission, **kwargs) -> None: """Remove the on-disk `.stl` after a Submission row is deleted. `FileField.delete(save=False)` is idempotent: it just calls `Storage.delete(name)`, and `FileSystemStorage.delete` catches `FileNotFoundError`. Safe to call on rows that never had a file (e.g. URL-source submissions) -- the `if instance.stl_file` truthiness check handles that. """ if instance.stl_file: instance.stl_file.delete(save=False)