Skip to content

Commit

Permalink
[1.5.x] Fixed #19652 -- Fixed .none() regression in related fields
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
akaariai committed Jan 23, 2013
1 parent 54887d6 commit f413214
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 2 deletions.
3 changes: 2 additions & 1 deletion django/db/models/fields/related.py
Expand Up @@ -498,7 +498,8 @@ def get_query_set(self):
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

Expand Down
21 changes: 21 additions & 0 deletions tests/modeltests/custom_managers/models.py
Expand Up @@ -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()
13 changes: 12 additions & 1 deletion tests/modeltests/custom_managers/tests.py
Expand Up @@ -3,7 +3,8 @@
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):
Expand Down Expand Up @@ -72,3 +73,13 @@ def test_manager(self):
],
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())

0 comments on commit f413214

Please sign in to comment.