Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #10672 -- Altered save_base to ensure that proxy models send a …

…post_save signal.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@10954 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 81aedbd157209518a2a25ac528f29893900c1ae5 1 parent 6cd37e0
Russell Keith-Magee authored June 08, 2009
29  django/db/models/base.py
@@ -411,29 +411,35 @@ def save(self, force_insert=False, force_update=False):
411 411
 
412 412
     save.alters_data = True
413 413
 
414  
-    def save_base(self, raw=False, cls=None, force_insert=False,
415  
-            force_update=False):
  414
+    def save_base(self, raw=False, cls=None, origin=None,
  415
+            force_insert=False, force_update=False):
416 416
         """
417 417
         Does the heavy-lifting involved in saving. Subclasses shouldn't need to
418 418
         override this method. It's separate from save() in order to hide the
419 419
         need for overrides of save() to pass around internal-only parameters
420  
-        ('raw' and 'cls').
  420
+        ('raw', 'cls', and 'origin').
421 421
         """
422 422
         assert not (force_insert and force_update)
423  
-        if not cls:
  423
+        if cls is None:
424 424
             cls = self.__class__
425  
-            meta = self._meta
426  
-            signal = True
427  
-            signals.pre_save.send(sender=self.__class__, instance=self, raw=raw)
  425
+            meta = cls._meta
  426
+            if not meta.proxy:
  427
+                origin = cls
428 428
         else:
429 429
             meta = cls._meta
430  
-            signal = False
  430
+
  431
+        if origin:
  432
+            signals.pre_save.send(sender=origin, instance=self, raw=raw)
431 433
 
432 434
         # If we are in a raw save, save the object exactly as presented.
433 435
         # That means that we don't try to be smart about saving attributes
434 436
         # that might have come from the parent class - we just save the
435 437
         # attributes we have been given to the class we have been given.
436 438
         if not raw:
  439
+            if meta.proxy:
  440
+                org = cls
  441
+            else:
  442
+                org = None
437 443
             for parent, field in meta.parents.items():
438 444
                 # At this point, parent's primary key field may be unknown
439 445
                 # (for example, from administration form which doesn't fill
@@ -441,7 +447,8 @@ def save_base(self, raw=False, cls=None, force_insert=False,
441 447
                 if field and getattr(self, parent._meta.pk.attname) is None and getattr(self, field.attname) is not None:
442 448
                     setattr(self, parent._meta.pk.attname, getattr(self, field.attname))
443 449
 
444  
-                self.save_base(cls=parent)
  450
+                self.save_base(cls=parent, origin=org)
  451
+
445 452
                 if field:
446 453
                     setattr(self, field.attname, self._get_pk_val(parent._meta))
447 454
             if meta.proxy:
@@ -492,8 +499,8 @@ def save_base(self, raw=False, cls=None, force_insert=False,
492 499
                     setattr(self, meta.pk.attname, result)
493 500
             transaction.commit_unless_managed()
494 501
 
495  
-        if signal:
496  
-            signals.post_save.send(sender=self.__class__, instance=self,
  502
+        if origin:
  503
+            signals.post_save.send(sender=origin, instance=self,
497 504
                 created=(not record_exists), raw=raw)
498 505
 
499 506
     save_base.alters_data = True
29  tests/modeltests/proxy_models/models.py
@@ -259,6 +259,33 @@ class Meta:
259 259
 >>> OtherPerson._default_manager.all()
260 260
 [<OtherPerson: barney>, <OtherPerson: wilma>]
261 261
 
  262
+# Test save signals for proxy models
  263
+>>> from django.db.models import signals
  264
+>>> def make_handler(model, event):
  265
+...     def _handler(*args, **kwargs):
  266
+...         print u"%s %s save" % (model, event)
  267
+...     return _handler
  268
+>>> h1 = make_handler('MyPerson', 'pre')
  269
+>>> h2 = make_handler('MyPerson', 'post')
  270
+>>> h3 = make_handler('Person', 'pre')
  271
+>>> h4 = make_handler('Person', 'post')
  272
+>>> signals.pre_save.connect(h1, sender=MyPerson)
  273
+>>> signals.post_save.connect(h2, sender=MyPerson)
  274
+>>> signals.pre_save.connect(h3, sender=Person)
  275
+>>> signals.post_save.connect(h4, sender=Person)
  276
+>>> dino = MyPerson.objects.create(name=u"dino")
  277
+MyPerson pre save
  278
+MyPerson post save
  279
+
  280
+# Test save signals for proxy proxy models
  281
+>>> h5 = make_handler('MyPersonProxy', 'pre')
  282
+>>> h6 = make_handler('MyPersonProxy', 'post')
  283
+>>> signals.pre_save.connect(h5, sender=MyPersonProxy)
  284
+>>> signals.post_save.connect(h6, sender=MyPersonProxy)
  285
+>>> dino = MyPersonProxy.objects.create(name=u"pebbles")
  286
+MyPersonProxy pre save
  287
+MyPersonProxy post save
  288
+
262 289
 # A proxy has the same content type as the model it is proxying for (at the
263 290
 # storage level, it is meant to be essentially indistinguishable).
264 291
 >>> ctype = ContentType.objects.get_for_model
@@ -266,7 +293,7 @@ class Meta:
266 293
 True
267 294
 
268 295
 >>> MyPersonProxy.objects.all()
269  
-[<MyPersonProxy: barney>, <MyPersonProxy: fred>]
  296
+[<MyPersonProxy: barney>, <MyPersonProxy: dino>, <MyPersonProxy: fred>, <MyPersonProxy: pebbles>]
270 297
 
271 298
 >>> u = User.objects.create(name='Bruce')
272 299
 >>> User.objects.all()

0 notes on commit 81aedbd

Please sign in to comment.
Something went wrong with that request. Please try again.