Author: russellm
Date: 2010-10-28 07:57:04 -0500 (Thu, 28 Oct 2010)
New Revision: 14389

Modified:
   django/trunk/django/db/models/fields/related.py
   django/trunk/tests/regressiontests/multiple_database/models.py
   django/trunk/tests/regressiontests/multiple_database/tests.py
Log:
Fixed #14471 -- Corrected a regression in the use of methods on custom managers 
on related querysets. Thanks to Lucky for the report.

Modified: django/trunk/django/db/models/fields/related.py
===================================================================
--- django/trunk/django/db/models/fields/related.py     2010-10-28 12:56:44 UTC 
(rev 14388)
+++ django/trunk/django/db/models/fields/related.py     2010-10-28 12:57:04 UTC 
(rev 14389)
@@ -420,7 +420,7 @@
             def create(self, **kwargs):
                 kwargs.update({rel_field.name: instance})
                 db = router.db_for_write(rel_model, instance=instance)
-                return super(RelatedManager, self).using(db).create(**kwargs)
+                return super(RelatedManager, 
self.db_manager(db)).create(**kwargs)
             create.alters_data = True
 
             def get_or_create(self, **kwargs):
@@ -428,7 +428,7 @@
                 # ForeignRelatedObjectsDescriptor knows about.
                 kwargs.update({rel_field.name: instance})
                 db = router.db_for_write(rel_model, instance=instance)
-                return super(RelatedManager, 
self).using(db).get_or_create(**kwargs)
+                return super(RelatedManager, 
self.db_manager(db)).get_or_create(**kwargs)
             get_or_create.alters_data = True
 
             # remove() and clear() are only provided if the ForeignKey can 
have a value of null.
@@ -517,7 +517,7 @@
                 opts = through._meta
                 raise AttributeError("Cannot use create() on a ManyToManyField 
which specifies an intermediary model. Use %s.%s's Manager instead." % 
(opts.app_label, opts.object_name))
             db = router.db_for_write(self.instance.__class__, 
instance=self.instance)
-            new_obj = super(ManyRelatedManager, 
self).using(db).create(**kwargs)
+            new_obj = super(ManyRelatedManager, 
self.db_manager(db)).create(**kwargs)
             self.add(new_obj)
             return new_obj
         create.alters_data = True
@@ -525,7 +525,7 @@
         def get_or_create(self, **kwargs):
             db = router.db_for_write(self.instance.__class__, 
instance=self.instance)
             obj, created = \
-                super(ManyRelatedManager, 
self).using(db).get_or_create(**kwargs)
+                super(ManyRelatedManager, 
self.db_manager(db)).get_or_create(**kwargs)
             # We only need to add() if created because if we got an object back
             # from get() then the relationship already exists.
             if created:

Modified: django/trunk/tests/regressiontests/multiple_database/models.py
===================================================================
--- django/trunk/tests/regressiontests/multiple_database/models.py      
2010-10-28 12:56:44 UTC (rev 14388)
+++ django/trunk/tests/regressiontests/multiple_database/models.py      
2010-10-28 12:57:04 UTC (rev 14389)
@@ -30,7 +30,21 @@
     class Meta:
         ordering = ('name',)
 
+# This book manager doesn't do anything interesting; it just
+# exists to strip out the 'extra_arg' argument to certain
+# calls. This argument is used to establish that the BookManager
+# is actually getting used when it should be.
+class BookManager(models.Manager):
+    def create(self, *args, **kwargs):
+        kwargs.pop('extra_arg', None)
+        return super(BookManager, self).create(*args, **kwargs)
+
+    def get_or_create(self, *args, **kwargs):
+        kwargs.pop('extra_arg', None)
+        return super(BookManager, self).get_or_create(*args, **kwargs)
+
 class Book(models.Model):
+    objects = BookManager()
     title = models.CharField(max_length=100)
     published = models.DateField()
     authors = models.ManyToManyField(Person)
@@ -60,4 +74,3 @@
 
     class Meta:
         ordering = ('flavor',)
-

Modified: django/trunk/tests/regressiontests/multiple_database/tests.py
===================================================================
--- django/trunk/tests/regressiontests/multiple_database/tests.py       
2010-10-28 12:56:44 UTC (rev 14388)
+++ django/trunk/tests/regressiontests/multiple_database/tests.py       
2010-10-28 12:57:04 UTC (rev 14389)
@@ -891,7 +891,29 @@
         except ValueError:
             pass
 
+    def test_related_manager(self):
+        "Related managers return managers, not querysets"
+        mark = Person.objects.using('other').create(name="Mark Pilgrim")
 
+        # extra_arg is removed by the BookManager's implementation of
+        # create(); but the BookManager's implementation won't get called
+        # unless edited returns a Manager, not a queryset
+        mark.book_set.create(title="Dive into Python",
+                             published=datetime.date(2009, 5, 4),
+                             extra_arg=True)
+
+        mark.book_set.get_or_create(title="Dive into Python",
+                                    published=datetime.date(2009, 5, 4),
+                                    extra_arg=True)
+
+        mark.edited.create(title="Dive into Water",
+                           published=datetime.date(2009, 5, 4),
+                           extra_arg=True)
+
+        mark.edited.get_or_create(title="Dive into Water",
+                                  published=datetime.date(2009, 5, 4),
+                                  extra_arg=True)
+
 class TestRouter(object):
     # A test router. The behaviour is vaguely master/slave, but the
     # databases aren't assumed to propagate changes.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to