#33505: Inconsistent Behavior with Abstract Models and Signals
-------------------------------------+-------------------------------------
Reporter: Ken | Owner: nobody
Weaver |
Type: Bug | Status: new
Component: Database | Version: 3.2
layer (models, ORM) |
Severity: Normal | Keywords:
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
Recently we came across an issue with abstract models and signals,
specifically many to many signals. It seems that for most signals, models
that have inherited from an abstract class (or perhaps any class) will not
also inherit the signals of that class. This is not unexpected. However,
for `m2m_changed` signals, the signal '''fires for every many to many
change in the entire application'''. I have created a minimum (ish)
working example [https://github.com/kenjones21/django_signal_bug here],
and I will paste the relevant code below as well.
I think ideally django would stop you from binding signals to abstract
models if they can't ever work, or spat out a warning when it was
attempted. If that isn't possible, never firing the signal would be
preferable to always firing the signal; the latter is highly likely to
break parts of your application you weren't testing.
Admittedly, I don't think the documentation ever specifies what the
behavior should be related to abstract/inherited models and signals. If
none of the changes here are possible, I think a warning in the
documentation on the model page, the signals page, or both would be
helpful, and I would be more than happy to work on that.
{{{
class Related(models.Model):
pass
class Abstract(models.Model):
m2m_field = models.ManyToManyField(to=Related)
int_field = models.IntegerField(default=0)
class Meta:
abstract = True
class OtherRelated(models.Model):
pass
class Other(models.Model):
m2m_field = models.ManyToManyField(to=OtherRelated)
@receiver(m2m_changed, sender=Abstract.m2m_field.through)
def abstract_m2m_signal(sender, **kwargs):
wrapped_abstract_m2m(sender, **kwargs)
}}}
{{{
@patch('app.models.wrapped_abstract_m2m', side_effect=mock_signal)
def test_abstract_m2m_signal_not_called(self, signal_mock):
other = Other.objects.create()
related = OtherRelated.objects.create()
other.m2m_field.add(related)
self.assertEqual(signal_mock.call_count, 0) # this fails
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/33505>
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 view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/053.ef679f62928e994a1ce7b265182f25d6%40djangoproject.com.