#24738: Possible bug in m2m_changed signal when deleting related objects
----------------------------------------------+--------------------
     Reporter:  No-0n3                        |      Owner:  nobody
         Type:  Bug                           |     Status:  new
    Component:  Database layer (models, ORM)  |    Version:  1.8
     Severity:  Normal                        |   Keywords:
 Triage Stage:  Unreviewed                    |  Has patch:  0
Easy pickings:  0                             |      UI/UX:  0
----------------------------------------------+--------------------
 Hi,

 Have observed that no m2m_changed signal is sent when a related object is
 deleted.

 If I explicitly clear the relations with "clear()" or remove the relation
 with "remove()", m2m_changed is correctly sent but if I delete it without
 calling "clear()" or "remove()" on the m2m field no signal is sent to
 indicate a change in relationship.

 Is this by design or should a m2m_changed signal be sent when a related
 object is deleted from the m2m table at deletion when the relations also
 are removed.

 Right now I've done a workaround by catching the "pre_delete" signal on my
 model that explicitly calls "clear()" on the M2M field to trigger the
 signal and catching it with my other signal function when it gets a
 "post_clear" action in m2m_changed signal.

 Here are my models and signals with my workaround:
 {{{
 from django.db import models
 from django.db.models.signals import m2m_changed, pre_delete
 from django.dispatch import receiver
 from django.db.models import Count


 # Models
 class Type(models.Model):
     name = models.CharField(max_length=200)

     def __unicode__(self):
         return unicode(self.name)


 class Blacklist(models.Model):
     source = models.URLField()
     name = models.CharField(max_length=200)
     date_added = models.DateField(auto_now_add=True)
     last_update = models.DateField(auto_now=True)
     types = models.ManyToManyField(Type)

     def __unicode__(self):
         return unicode(self.name)


 class Record(models.Model):
     blacklists = models.ManyToManyField(Blacklist)
     ip = models.GenericIPAddressField(protocol='IPv4', unique=True)

     def __unicode__(self):
         return unicode(self.ip)


 # Signal actions
 @receiver(m2m_changed, sender=Record.blacklists.through)
 def blacklists_changed(sender, **kwargs):
     if kwargs['action'] == "post_clear":
         if kwargs['reverse']:
 
Record.objects.annotate(count=Count('blacklists')).exclude(count__gt=0).delete()


 @receiver(pre_delete, sender=Blacklist)
 def blacklist_deleted(sender, **kwargs):
     kwargs['instance'].record_set.clear()
 }}}

 If you comment out the blacklist_deleted and do a <Blacklist
 instance>.delete() no m2m_changed signal is sent at all.

 BR / Isaac

--
Ticket URL: <https://code.djangoproject.com/ticket/24738>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/049.962d57c72f0148c070d77f4329e38559%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to