mirror of
https://github.com/Hopiu/django-model-utils.git
synced 2026-05-27 19:13:59 +00:00
Provide dir() support for PassThroughManagers.
Reported in #55 by erikcw.
This commit is contained in:
parent
b5b5864d5f
commit
8a1d0662f1
3 changed files with 54 additions and 0 deletions
|
|
@ -4,6 +4,12 @@ CHANGES
|
||||||
master (unreleased)
|
master (unreleased)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
* ``PassThroughManager`` now has support for seeing exposed methods via
|
||||||
|
``dir``, allowing `IPython`_ tab completion to be useful. Merge of GH-104,
|
||||||
|
fixes GH-55.
|
||||||
|
|
||||||
|
.. _IPython: http://ipython.org/
|
||||||
|
|
||||||
|
|
||||||
2.0.3 (2014.03.19)
|
2.0.3 (2014.03.19)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
|
||||||
|
|
@ -244,6 +244,20 @@ class PassThroughManagerMixin(object):
|
||||||
return getattr(self.get_query_set(), name)
|
return getattr(self.get_query_set(), name)
|
||||||
return getattr(self.get_queryset(), name)
|
return getattr(self.get_queryset(), name)
|
||||||
|
|
||||||
|
def __dir__(self):
|
||||||
|
"""
|
||||||
|
Allow introspection via dir() and ipythonesque tab-discovery.
|
||||||
|
|
||||||
|
We do dir(type(self)) because to do dir(self) would be a recursion
|
||||||
|
error.
|
||||||
|
We call dir(self.get_query_set()) because it is possible that the
|
||||||
|
queryset returned by get_query_set() is interesting, even if
|
||||||
|
self._queryset_cls is None.
|
||||||
|
"""
|
||||||
|
my_values = frozenset(dir(type(self)))
|
||||||
|
my_values |= frozenset(dir(self.get_query_set()))
|
||||||
|
return list(my_values)
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
try:
|
try:
|
||||||
qs = super(PassThroughManagerMixin, self).get_queryset()
|
qs = super(PassThroughManagerMixin, self).get_queryset()
|
||||||
|
|
|
||||||
|
|
@ -1235,6 +1235,40 @@ class PassThroughManagerTests(TestCase):
|
||||||
self.assertFalse(hasattr(dude.cars_owned, 'by_name'))
|
self.assertFalse(hasattr(dude.cars_owned, 'by_name'))
|
||||||
|
|
||||||
|
|
||||||
|
def test_using_dir(self):
|
||||||
|
# make sure introspecing via dir() doesn't actually cause queries,
|
||||||
|
# just as a sanity check.
|
||||||
|
with self.assertNumQueries(0):
|
||||||
|
querysets_to_dir = (
|
||||||
|
Dude.objects,
|
||||||
|
Dude.objects.by_name('Duder'),
|
||||||
|
Dude.objects.all().by_name('Duder'),
|
||||||
|
Dude.abiders,
|
||||||
|
Dude.abiders.rug_positive(),
|
||||||
|
Dude.abiders.all().rug_positive()
|
||||||
|
)
|
||||||
|
for qs in querysets_to_dir:
|
||||||
|
self.assertTrue('by_name' in dir(qs))
|
||||||
|
self.assertTrue('abiding' in dir(qs))
|
||||||
|
self.assertTrue('rug_positive' in dir(qs))
|
||||||
|
self.assertTrue('rug_negative' in dir(qs))
|
||||||
|
# some standard qs methods
|
||||||
|
self.assertTrue('count' in dir(qs))
|
||||||
|
self.assertTrue('order_by' in dir(qs))
|
||||||
|
self.assertTrue('select_related' in dir(qs))
|
||||||
|
# make sure it's been de-duplicated
|
||||||
|
self.assertEqual(1, dir(qs).count('distinct'))
|
||||||
|
|
||||||
|
# manager only method.
|
||||||
|
self.assertTrue('get_stats' in dir(Dude.abiders))
|
||||||
|
# manager only method shouldn't appear on the non AbidingManager
|
||||||
|
self.assertFalse('get_stats' in dir(Dude.objects))
|
||||||
|
# standard manager methods
|
||||||
|
self.assertTrue('get_query_set' in dir(Dude.abiders))
|
||||||
|
self.assertTrue('contribute_to_class' in dir(Dude.abiders))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CreatePassThroughManagerTests(TestCase):
|
class CreatePassThroughManagerTests(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.dude = Dude.objects.create(name='El Duderino')
|
self.dude = Dude.objects.create(name='El Duderino')
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue