Avoid auto-proxying all methods to the queryset.

This is unwanted behavior, and django provides much better methods for
it instead. (PolymorphicQuerySet.as_manager() / PolymorphicManager.from_queryset()
fix_request_path_info
Diederik van der Boor 2015-12-28 17:10:58 +01:00
parent 9e2c11beb8
commit 009069a32b
3 changed files with 17 additions and 14 deletions

View File

@ -38,18 +38,18 @@ class PolymorphicManager(models.Manager):
if django.VERSION < (1, 7): if django.VERSION < (1, 7):
get_query_set = get_queryset get_query_set = get_queryset
# Proxy all unknown method calls to the queryset, so that its members are
# directly accessible as PolymorphicModel.objects.*
# The advantage of this method is that not yet known member functions of derived querysets will be proxied as well.
# We exclude any special functions (__) from this automatic proxying.
#
# NOTE: Fetching the queryset is done by calling self.all() here on purpose.
# By using .all(), the proper get_query_set()/get_queryset() will be used for each Django version.
# Django 1.4/1.5 need to use get_query_set(), because the RelatedManager overrides that.
def __getattr__(self, name):
if name.startswith('__'):
return super(PolymorphicManager, self).__getattr__(self, name)
return getattr(self.all(), name)
def __unicode__(self): def __unicode__(self):
return '%s (PolymorphicManager) using %s' % (self.__class__.__name__, self.queryset_class.__name__) return '%s (PolymorphicManager) using %s' % (self.__class__.__name__, self.queryset_class.__name__)
# Proxied methods
def non_polymorphic(self):
return self.all().non_polymorphic()
def instance_of(self, *args):
return self.all().instance_of(*args)
def not_instance_of(self, *args):
return self.all().not_instance_of(*args)
def get_real_instances(self, base_result_objects=None):
return self.all().get_real_instances(base_result_objects=base_result_objects)

View File

@ -82,7 +82,7 @@ class PolymorphicQuerySet(QuerySet):
as_manager.queryset_only = True as_manager.queryset_only = True
as_manager = classmethod(as_manager) as_manager = classmethod(as_manager)
def non_polymorphic(self, *args, **kwargs): def non_polymorphic(self):
"""switch off polymorphic behaviour for this query. """switch off polymorphic behaviour for this query.
When the queryset is evaluated, only objects of the type of the When the queryset is evaluated, only objects of the type of the
base class used for this query are returned.""" base class used for this query are returned."""

View File

@ -174,6 +174,9 @@ class MyManager(PolymorphicManager):
def get_queryset(self): def get_queryset(self):
return super(MyManager, self).get_queryset().order_by('-field1') return super(MyManager, self).get_queryset().order_by('-field1')
def my_queryset_foo(self):
return self.all().my_queryset_foo()
# Django <= 1.5 compatibility # Django <= 1.5 compatibility
get_query_set = get_queryset get_query_set = get_queryset