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
-~----------~----~----~----~------~----~------~--~---

Reply via email to