diff --git a/django/db/models/base.py b/django/db/models/base.py index 3d40bc4286..14ca922b05 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -459,14 +459,16 @@ class ModelState: class Model(AltersData, metaclass=ModelBase): def __init__(self, *args, **kwargs): # Alias some things as locals to avoid repeat global lookups - cls = self.__class__ + cls = sender = self.__class__ opts = self._meta _setattr = setattr _DEFERRED = DEFERRED if opts.abstract: raise TypeError("Abstract models cannot be instantiated.") - pre_init.send(sender=cls, args=args, kwargs=kwargs) + if sender._meta.proxy: + sender = sender._meta.concrete_model + pre_init.send(sender=sender, args=args, kwargs=kwargs) # Set up the storage for instance state self._state = ModelState() @@ -569,7 +571,7 @@ class Model(AltersData, metaclass=ModelBase): f"{unexpected_names}" ) super().__init__() - post_init.send(sender=cls, instance=self) + post_init.send(sender=sender, instance=self) @classmethod def from_db(cls, db, field_names, values): @@ -950,14 +952,13 @@ class Model(AltersData, metaclass=ModelBase): using = using or router.db_for_write(self.__class__, instance=self) assert not (force_insert and (force_update or update_fields)) assert update_fields is None or update_fields - cls = origin = self.__class__ - # Skip proxies, but keep the origin as the proxy model. + cls = self.__class__ if cls._meta.proxy: cls = cls._meta.concrete_model meta = cls._meta if not meta.auto_created: pre_save.send( - sender=origin, + sender=cls, instance=self, raw=raw, using=using, @@ -992,7 +993,7 @@ class Model(AltersData, metaclass=ModelBase): # Signal that the save is complete if not meta.auto_created: post_save.send( - sender=origin, + sender=cls, instance=self, created=(not updated), update_fields=update_fields, diff --git a/django/db/models/deletion.py b/django/db/models/deletion.py index fd3d290a96..42d731e6ad 100644 --- a/django/db/models/deletion.py +++ b/django/db/models/deletion.py @@ -456,6 +456,8 @@ class Collector: # send pre_delete signals for model, obj in self.instances_with_model(): if not model._meta.auto_created: + if model._meta.proxy: + model = model._meta.concrete_model signals.pre_delete.send( sender=model, instance=obj, @@ -504,6 +506,8 @@ class Collector: deleted_counter[model._meta.label] += count if not model._meta.auto_created: + if model._meta.proxy: + model = model._meta.concrete_model for obj in instances: signals.post_delete.send( sender=model, diff --git a/tests/defer_regress/tests.py b/tests/defer_regress/tests.py index 10100e348d..7b9dfdfe35 100644 --- a/tests/defer_regress/tests.py +++ b/tests/defer_regress/tests.py @@ -343,5 +343,5 @@ class DeferDeletionSignalsTests(TestCase): def test_delete_defered_proxy_model(self): Proxy.objects.only("value").get(pk=self.item_pk).delete() - self.assertEqual(self.pre_delete_senders, [Proxy]) - self.assertEqual(self.post_delete_senders, [Proxy]) + self.assertEqual(self.pre_delete_senders, [Item]) + self.assertEqual(self.post_delete_senders, [Item]) diff --git a/tests/proxy_models/tests.py b/tests/proxy_models/tests.py index 7caa43d489..9014be6b54 100644 --- a/tests/proxy_models/tests.py +++ b/tests/proxy_models/tests.py @@ -243,7 +243,7 @@ class ProxyModelTests(TestCase): signals.post_save.connect(h4, sender=Person) MyPerson.objects.create(name="dino") - self.assertEqual(output, ["MyPerson pre save", "MyPerson post save"]) + self.assertEqual(output, ["Person pre save", "Person post save"]) output = [] @@ -255,7 +255,7 @@ class ProxyModelTests(TestCase): MyPersonProxy.objects.create(name="pebbles") - self.assertEqual(output, ["MyPersonProxy pre save", "MyPersonProxy post save"]) + self.assertEqual(output, ["Person pre save", "Person post save"]) signals.pre_save.disconnect(h1, sender=MyPerson) signals.post_save.disconnect(h2, sender=MyPerson)