summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnssi Kääriäinen <akaariai@gmail.com>2013-01-23 08:22:07 +0200
committerAnssi Kääriäinen <akaariai@gmail.com>2013-01-23 08:26:34 +0200
commitf4132140f52c88b67d11743d4062a9d455959ffc (patch)
treeb4adad0e25309f1dd084c106c5e8e8c86915800b
parent54887d686b1552ae98e3eb4fa57a64036eea72a5 (diff)
[1.5.x] Fixed #19652 -- Fixed .none() regression in related fields
The regression was caused by using .none() when querying for related models, and the origin field's value was None. This resulted in missing custom related manager subclass as .none() returns plain QuerySet. This isn't backport from master, in master .none() correctly preserves the queryset's class. Patch provided by Simon Charette, with some minor polish by committer.
-rw-r--r--django/db/models/fields/related.py3
-rw-r--r--tests/modeltests/custom_managers/models.py21
-rw-r--r--tests/modeltests/custom_managers/tests.py13
3 files changed, 35 insertions, 2 deletions
diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
index 2e390c56eb..ead1d49b57 100644
--- a/django/db/models/fields/related.py
+++ b/django/db/models/fields/related.py
@@ -498,7 +498,8 @@ class ForeignRelatedObjectsDescriptor(object):
db = self._db or router.db_for_read(self.model, instance=self.instance)
qs = super(RelatedManager, self).get_query_set().using(db).filter(**self.core_filters)
if getattr(self.instance, attname) is None:
- return qs.none()
+ # We don't want to use qs.none() here, see #19652
+ return qs.filter(pk__in=[])
qs._known_related_objects = {rel_field: {self.instance.pk: self.instance}}
return qs
diff --git a/tests/modeltests/custom_managers/models.py b/tests/modeltests/custom_managers/models.py
index de7c1772ed..f224ec0f6c 100644
--- a/tests/modeltests/custom_managers/models.py
+++ b/tests/modeltests/custom_managers/models.py
@@ -63,3 +63,24 @@ class Car(models.Model):
def __str__(self):
return self.name
+
+
+# Bug #19652
+class ObjectQuerySet(models.query.QuerySet):
+ pass
+
+class ObjectManager(models.Manager):
+ use_for_related_fields = True
+
+ def get_query_set(self):
+ return ObjectQuerySet(self.model, using=self._db)
+
+
+class RelatedObject(models.Model):
+ pass
+
+
+class Object(models.Model):
+ related = models.ForeignKey(RelatedObject, related_name='objs')
+
+ objects = ObjectManager()
diff --git a/tests/modeltests/custom_managers/tests.py b/tests/modeltests/custom_managers/tests.py
index 294920de2b..aa2e3e208d 100644
--- a/tests/modeltests/custom_managers/tests.py
+++ b/tests/modeltests/custom_managers/tests.py
@@ -3,7 +3,8 @@ from __future__ import absolute_import
from django.test import TestCase
from django.utils import six
-from .models import Person, Book, Car, PersonManager, PublishedBookManager
+from .models import (ObjectQuerySet, RelatedObject, Person, Book, Car, PersonManager,
+ PublishedBookManager)
class CustomManagerTests(TestCase):
@@ -72,3 +73,13 @@ class CustomManagerTests(TestCase):
],
lambda c: c.name
)
+
+ def test_related_manager(self):
+ """
+ Make sure un-saved object's related managers always return an instance
+ of the same class the manager's `get_query_set` returns. Refs #19652.
+ """
+ rel_qs = RelatedObject().objs.all()
+ self.assertIsInstance(rel_qs, ObjectQuerySet)
+ with self.assertNumQueries(0):
+ self.assertFalse(rel_qs.exists())