I'm using Django 3 and Python 3.8. I have the following model ...
class Coop(models.Model):
objects = CoopManager()
name = models.CharField(max_length=250, null=False)
types = models.ManyToManyField(CoopType, blank=False)
addresses = models.ManyToManyField(Address)
enabled = models.BooleanField(default=True, null=False)
phone = models.ForeignKey(ContactMethod, on_delete=models.CASCADE, null=True, related_name='contact_phone')
email = models.ForeignKey(ContactMethod, on_delete=models.CASCADE, null=True, related_name='contact_email')
web_site = models.TextField()
Note the "phone" and "email" foreign key columns. Is there any Django/Python specific way to automatically remove the ContactMethod records once they become orphaned? That is, if I have my model, in which both columns are populated, and then run
coop.phone = None
coop.save(update_fields=['phone'])
Is there anything that will automatically delete the orphaned records? Or I guess what is the standard way to achieve this? I'm running a MySql 8 db, but i would prefer to exclude DB-specific solutions.
You can define a Django signal, but Django signals do not always run. Especially when you make ORM calls that perform bulk updates or bulk removals. For example if you set the
emailand/orphoneof allCoops withenabled=FalsewithCoop.objects.filter(enabled=False).update(email=None, phone=None), then it will not runpost_savesignals, and thus someContactMethods can be orphaned without the signal being triggered.Even if you could use a signal, it might not be a good idea. One can also make updates to the database without the ORM query, for example the database administrator through the PhpMyAdmin frontend. So even if it was possible in Django, it would mean one can still orphan objects through another way. Furthermore such signal would handle one
ContactMethodat the time, which is more expensive than deletingContactMethods in bulk.You can make a management command [Django-doc] that you can run periodically, for example once a day. You can define such management command in your
app:In the
app/management/commands/remove_orphan_contactmethod.py, you can then detect and remove theseContactMethodobjects:Then you can run:
To run the command. You can for example specify a cronjob [wiki] or some other recurring task mechanism to perform this command at a certain frequency.