Commits

Rajeesh Nair committed 555736b

Django-monitor: Auto-deletion of monitor entries

* When an instance of a moderated model is deleted, monitor_entries
corresponding to the instance and all of its parents are deleted.

Comments (0)

Files changed (3)

 from django.db.models import signals
 from django.db.models.loading import get_model
 
-from monitor.util import create_moderate_perms, add_fields, save_handler
+from monitor.util import (
+    create_moderate_perms, add_fields, save_handler, delete_handler
+)
 
 _queue = {}
 
     """ Register(enqueue) the model for moderation."""
     if not model_from_queue(model):
         signals.post_save.connect(save_handler, sender = model)
+        signals.pre_delete.connect(delete_handler, sender = model)
         registered_model = get_model(
             model._meta.app_label, model._meta.object_name, False
         )

monitor/tests/apps/testapp/tests.py

         self.assertEquals(eb1.is_approved, True)
         self.assertEquals(eb1.book_ptr.is_approved, True)
 
+    def test_5_auto_delete_monitor_entries(self):
+        """
+        When an instance of a moderated model is deleted, the monitor entries
+        corresponding to the instance and all of its parent instances also
+        should be deleted.
+        """
+        from monitor.models import MonitorEntry
+
+        self.assertEquals(MonitorEntry.objects.count(), 0)
+        ebook_ct = ContentType.objects.get_for_model(EBook)
+        book_ct = ContentType.objects.get_for_model(Book)
+
+        pub1 = Publisher.objects.create(
+            name = 'test_pub', num_awards = 3
+        )
+        auth1 = Author.objects.create(
+           name = 'test_auth', age = 34
+        )
+        eb1 = EBook.objects.create(
+            isbn='123456789', name='test_ebook', pages=300, publisher = pub1
+        )
+        eb1.authors = [auth1]
+        eb1.save()
+
+        # 1 monitor_entry each for auth1, eb1 & its parent, eb1.book_ptr.
+        self.assertEquals(MonitorEntry.objects.count(), 3)
+        ebook_mes = MonitorEntry.objects.filter(content_type = ebook_ct)
+        book_mes = MonitorEntry.objects.filter(content_type = book_ct)
+        self.assertEquals(ebook_mes.count(), 1)
+        self.assertEquals(book_mes.count(), 1)
+
+        eb1.delete()
+        # MonitorEntry object for auth1 remains. Others removed.
+        self.assertEquals(MonitorEntry.objects.count(), 1)
+        ebook_mes = MonitorEntry.objects.filter(content_type = ebook_ct)
+        book_mes = MonitorEntry.objects.filter(content_type = book_ct)
+        self.assertEquals(ebook_mes.count(), 0)
+        self.assertEquals(book_mes.count(), 0) 
+
                 if rel_obj:
                     moderate_rel_objects(rel_obj, status, user)
 
+def delete_handler(sender, instance, **kwargs):
+    """ When an instance is deleted, delete corresponding monitor_entries too"""
+    from monitor import model_from_queue
+    if model_from_queue(sender):
+        me = MonitorEntry.objects.get_for_instance(instance)
+        if me:
+            me.delete()
+        # Delete monitor_entries of parents too
+        monitored_parents = filter(
+            lambda x: model_from_queue(x),
+            instance._meta.parents.keys()
+        )
+        for parent in monitored_parents:
+            parent_ct = ContentType.objects.get_for_model(parent)
+            parent_pk_field = instance._meta.get_ancestor_link(parent)
+            parent_pk = getattr(instance, parent_pk_field.attname)
+            try:
+                me = MonitorEntry.objects.get(
+                    content_type = parent_ct, object_id = parent_pk
+                )
+                me.delete()
+            except MonitorEntry.DoesNotExist:
+                pass