From 7e381179e484040541d7bd7b98529c1f4773be43 Mon Sep 17 00:00:00 2001 From: Andy Freeland Date: Fri, 24 May 2013 15:24:37 -0400 Subject: [PATCH] PassThroughManager calls superclass `get_query_set`. As discussed in #31, PassThroughManager and PassThroughManager.for_queryset_class() would ignore the superclass version of `get_query_set`. --- AUTHORS.rst | 1 + CHANGES.rst | 3 +++ model_utils/managers.py | 12 +++++------- model_utils/tests/models.py | 8 +++++++- model_utils/tests/tests.py | 15 +++++++++++++-- 5 files changed, 29 insertions(+), 10 deletions(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index 7155d28..185ccf1 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -17,3 +17,4 @@ Simon Meers sayane Trey Hunner zyegfryed +Andy Freeland diff --git a/CHANGES.rst b/CHANGES.rst index 4870ea6..28291fb 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,9 @@ CHANGES tip (unreleased) ---------------- +- ``PassThroughManager.for_queryset_class()`` no longer ignores superclass + ``get_query_set``. + - Fixed ``InheritanceManager`` bug with grandchildren in Django 1.6. Thanks CrazyCasta. diff --git a/model_utils/managers.py b/model_utils/managers.py index 80b7621..231bffa 100644 --- a/model_utils/managers.py +++ b/model_utils/managers.py @@ -164,11 +164,10 @@ class PassThroughManager(models.Manager): return getattr(self.get_query_set(), name) def get_query_set(self): + qs = super(PassThroughManager, self).get_query_set() if self._queryset_cls is not None: - kwargs = {'model': self.model} - kwargs['using'] = self._db - return self._queryset_cls(**kwargs) - return super(PassThroughManager, self).get_query_set() + qs = qs._clone(klass=self._queryset_cls) + return qs @classmethod def for_queryset_class(cls, queryset_cls): @@ -181,9 +180,8 @@ def create_pass_through_manager_for_queryset_class(base, queryset_cls): return super(_PassThroughManager, self).__init__() def get_query_set(self): - kwargs = {} - kwargs["using"] = self._db - return queryset_cls(self.model, **kwargs) + qs = super(_PassThroughManager, self).get_query_set() + return qs._clone(klass=queryset_cls) def __reduce__(self): # our pickling support breaks for subclasses (e.g. RelatedManager) diff --git a/model_utils/tests/models.py b/model_utils/tests/models.py index 08ba31f..55c242b 100644 --- a/model_utils/tests/models.py +++ b/model_utils/tests/models.py @@ -208,6 +208,11 @@ class Car(models.Model): objects = PassThroughManager(DudeQuerySet) +class SpotManager(PassThroughManager): + def get_query_set(self): + return super(SpotManager, self).get_query_set().filter(secret=False) + + class SpotQuerySet(models.query.QuerySet): def closed(self): return self.filter(closed=True) @@ -220,9 +225,10 @@ class Spot(models.Model): name = models.CharField(max_length=20) secure = models.BooleanField(default=True) closed = models.BooleanField(default=False) + secret = models.BooleanField(default=False) owner = models.ForeignKey(Dude, related_name='spots_owned') - objects = PassThroughManager.for_queryset_class(SpotQuerySet)() + objects = SpotManager.for_queryset_class(SpotQuerySet)() class Tracked(models.Model): diff --git a/model_utils/tests/tests.py b/model_utils/tests/tests.py index 6eb90f8..fac89f7 100644 --- a/model_utils/tests/tests.py +++ b/model_utils/tests/tests.py @@ -646,17 +646,28 @@ class CreatePassThroughManagerTests(TestCase): def test_reverse_manager(self): Spot.objects.create( - name='The Crib', owner=self.dude, closed=True, secure=True) + name='The Crib', owner=self.dude, closed=True, secure=True, + secret=False) self.assertEqual(self.dude.spots_owned.closed().count(), 1) def test_related_queryset_pickling(self): Spot.objects.create( - name='The Crib', owner=self.dude, closed=True, secure=True) + name='The Crib', owner=self.dude, closed=True, secure=True, + secret=False) qs = self.dude.spots_owned.closed() pickled_qs = pickle.dumps(qs) unpickled_qs = pickle.loads(pickled_qs) self.assertEqual(unpickled_qs.secured().count(), 1) + def test_related_queryset_superclass_method(self): + Spot.objects.create( + name='The Crib', owner=self.dude, closed=True, secure=True, + secret=False) + Spot.objects.create( + name='The Secret Crib', owner=self.dude, closed=False, secure=True, + secret=True) + self.assertEqual(self.dude.spots_owned.count(), 1) + def test_related_manager_create(self): self.dude.spots_owned.create(name='The Crib', closed=True, secure=True)