Author: russellm Date: 2009-06-08 08:04:22 -0500 (Mon, 08 Jun 2009) New Revision: 10954
Modified: django/trunk/django/db/models/base.py django/trunk/tests/modeltests/proxy_models/models.py Log: Fixed #10672 -- Altered save_base to ensure that proxy models send a post_save signal. Modified: django/trunk/django/db/models/base.py =================================================================== --- django/trunk/django/db/models/base.py 2009-06-08 05:29:47 UTC (rev 10953) +++ django/trunk/django/db/models/base.py 2009-06-08 13:04:22 UTC (rev 10954) @@ -411,29 +411,35 @@ save.alters_data = True - def save_base(self, raw=False, cls=None, force_insert=False, - force_update=False): + def save_base(self, raw=False, cls=None, origin=None, + force_insert=False, force_update=False): """ Does the heavy-lifting involved in saving. Subclasses shouldn't need to override this method. It's separate from save() in order to hide the need for overrides of save() to pass around internal-only parameters - ('raw' and 'cls'). + ('raw', 'cls', and 'origin'). """ assert not (force_insert and force_update) - if not cls: + if cls is None: cls = self.__class__ - meta = self._meta - signal = True - signals.pre_save.send(sender=self.__class__, instance=self, raw=raw) + meta = cls._meta + if not meta.proxy: + origin = cls else: meta = cls._meta - signal = False + if origin: + signals.pre_save.send(sender=origin, instance=self, raw=raw) + # If we are in a raw save, save the object exactly as presented. # That means that we don't try to be smart about saving attributes # that might have come from the parent class - we just save the # attributes we have been given to the class we have been given. if not raw: + if meta.proxy: + org = cls + else: + org = None for parent, field in meta.parents.items(): # At this point, parent's primary key field may be unknown # (for example, from administration form which doesn't fill @@ -441,7 +447,8 @@ if field and getattr(self, parent._meta.pk.attname) is None and getattr(self, field.attname) is not None: setattr(self, parent._meta.pk.attname, getattr(self, field.attname)) - self.save_base(cls=parent) + self.save_base(cls=parent, origin=org) + if field: setattr(self, field.attname, self._get_pk_val(parent._meta)) if meta.proxy: @@ -492,8 +499,8 @@ setattr(self, meta.pk.attname, result) transaction.commit_unless_managed() - if signal: - signals.post_save.send(sender=self.__class__, instance=self, + if origin: + signals.post_save.send(sender=origin, instance=self, created=(not record_exists), raw=raw) save_base.alters_data = True Modified: django/trunk/tests/modeltests/proxy_models/models.py =================================================================== --- django/trunk/tests/modeltests/proxy_models/models.py 2009-06-08 05:29:47 UTC (rev 10953) +++ django/trunk/tests/modeltests/proxy_models/models.py 2009-06-08 13:04:22 UTC (rev 10954) @@ -259,6 +259,33 @@ >>> OtherPerson._default_manager.all() [<OtherPerson: barney>, <OtherPerson: wilma>] +# Test save signals for proxy models +>>> from django.db.models import signals +>>> def make_handler(model, event): +... def _handler(*args, **kwargs): +... print u"%s %s save" % (model, event) +... return _handler +>>> h1 = make_handler('MyPerson', 'pre') +>>> h2 = make_handler('MyPerson', 'post') +>>> h3 = make_handler('Person', 'pre') +>>> h4 = make_handler('Person', 'post') +>>> signals.pre_save.connect(h1, sender=MyPerson) +>>> signals.post_save.connect(h2, sender=MyPerson) +>>> signals.pre_save.connect(h3, sender=Person) +>>> signals.post_save.connect(h4, sender=Person) +>>> dino = MyPerson.objects.create(name=u"dino") +MyPerson pre save +MyPerson post save + +# Test save signals for proxy proxy models +>>> h5 = make_handler('MyPersonProxy', 'pre') +>>> h6 = make_handler('MyPersonProxy', 'post') +>>> signals.pre_save.connect(h5, sender=MyPersonProxy) +>>> signals.post_save.connect(h6, sender=MyPersonProxy) +>>> dino = MyPersonProxy.objects.create(name=u"pebbles") +MyPersonProxy pre save +MyPersonProxy post save + # A proxy has the same content type as the model it is proxying for (at the # storage level, it is meant to be essentially indistinguishable). >>> ctype = ContentType.objects.get_for_model @@ -266,7 +293,7 @@ True >>> MyPersonProxy.objects.all() -[<MyPersonProxy: barney>, <MyPersonProxy: fred>] +[<MyPersonProxy: barney>, <MyPersonProxy: dino>, <MyPersonProxy: fred>, <MyPersonProxy: pebbles>] >>> u = User.objects.create(name='Bruce') >>> User.objects.all() --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django updates" group. To post to this group, send email to django-updates@googlegroups.com To unsubscribe from this group, send email to django-updates+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-updates?hl=en -~----------~----~----~----~------~----~------~--~---