We have a tagging system for users to filter their files by defined tags.
Here's how the models are set up:
class Tags(models.Model):
name = models.CharField(max_length=100)
user = models.ForeignKey(User)
class Files(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=100)
tags = models.ManyToManyField(Tags, null=True, blank=True)
Now, because tags are not required, when we remove tags from a file they don't get deleted. This leaves a bunch of tags saved on our database and we want to clean them up.
I've tried redefining the save method on the Files model, and the clean method.
I've tried connecting an m2m_changed signal on the Files model: https://docs.djangoproject.com/en/dev/ref/signals/#m2m-changed
Last thing I tried was a pre_save signal: https://docs.djangoproject.com/en/dev/ref/signals/#pre-save
I was planning to iterate over the tags and delete the ones with empty files_set
, but using these methods I can't reliably figure that out (i.e. I end up removing tags that aren't associated but are about to be associated (because m2m_changed fires several times with different actions)).
Here's what I thought would work:
def handle_tags (sender, instance, *args, **kwargs) :
action = kwargs.get('action')
if action == 'post_clear':
# search through users tags... I guess?
tags = Tags.objects.filter(user=instance.user)
for tag in tags:
if not tag.files_set.exists():
tag.delete()
return
m2m_changed.connect(handle_tags, sender=Files.tags.through)
But, as I said, it will delete a tag before it is added (and if it's added, we obviously don't want to delete it).