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())