mirror of
https://github.com/Hopiu/django-model-utils.git
synced 2026-05-23 00:55:48 +00:00
Fix select_subclasses for Django 1.8.
This commit is contained in:
parent
3110794afc
commit
3f9b1cfac8
1 changed files with 20 additions and 16 deletions
|
|
@ -8,7 +8,7 @@ from django.core.exceptions import ObjectDoesNotExist
|
||||||
try:
|
try:
|
||||||
from django.db.models.constants import LOOKUP_SEP
|
from django.db.models.constants import LOOKUP_SEP
|
||||||
from django.utils.six import string_types
|
from django.utils.six import string_types
|
||||||
except ImportError: # Django < 1.5
|
except ImportError: # Django < 1.5
|
||||||
from django.db.models.sql.constants import LOOKUP_SEP
|
from django.db.models.sql.constants import LOOKUP_SEP
|
||||||
string_types = (basestring,)
|
string_types = (basestring,)
|
||||||
|
|
||||||
|
|
@ -53,20 +53,18 @@ class InheritanceQuerySetMixin(object):
|
||||||
new_qs.subclasses = subclasses
|
new_qs.subclasses = subclasses
|
||||||
return new_qs
|
return new_qs
|
||||||
|
|
||||||
|
|
||||||
def _clone(self, klass=None, setup=False, **kwargs):
|
def _clone(self, klass=None, setup=False, **kwargs):
|
||||||
for name in ['subclasses', '_annotated']:
|
for name in ['subclasses', '_annotated']:
|
||||||
if hasattr(self, name):
|
if hasattr(self, name):
|
||||||
kwargs[name] = getattr(self, name)
|
kwargs[name] = getattr(self, name)
|
||||||
return super(InheritanceQuerySetMixin, self)._clone(klass, setup, **kwargs)
|
return super(InheritanceQuerySetMixin, self)._clone(
|
||||||
|
klass, setup, **kwargs)
|
||||||
|
|
||||||
def annotate(self, *args, **kwargs):
|
def annotate(self, *args, **kwargs):
|
||||||
qset = super(InheritanceQuerySetMixin, self).annotate(*args, **kwargs)
|
qset = super(InheritanceQuerySetMixin, self).annotate(*args, **kwargs)
|
||||||
qset._annotated = [a.default_alias for a in args] + list(kwargs.keys())
|
qset._annotated = [a.default_alias for a in args] + list(kwargs.keys())
|
||||||
return qset
|
return qset
|
||||||
|
|
||||||
|
|
||||||
def iterator(self):
|
def iterator(self):
|
||||||
iter = super(InheritanceQuerySetMixin, self).iterator()
|
iter = super(InheritanceQuerySetMixin, self).iterator()
|
||||||
if getattr(self, 'subclasses', False):
|
if getattr(self, 'subclasses', False):
|
||||||
|
|
@ -95,7 +93,6 @@ class InheritanceQuerySetMixin(object):
|
||||||
for obj in iter:
|
for obj in iter:
|
||||||
yield obj
|
yield obj
|
||||||
|
|
||||||
|
|
||||||
def _get_subclasses_recurse(self, model, levels=None):
|
def _get_subclasses_recurse(self, model, levels=None):
|
||||||
"""
|
"""
|
||||||
Given a Model class, find all related objects, exploring children
|
Given a Model class, find all related objects, exploring children
|
||||||
|
|
@ -115,11 +112,11 @@ class InheritanceQuerySetMixin(object):
|
||||||
if levels or levels is None:
|
if levels or levels is None:
|
||||||
for subclass in self._get_subclasses_recurse(
|
for subclass in self._get_subclasses_recurse(
|
||||||
rel.field.model, levels=levels):
|
rel.field.model, levels=levels):
|
||||||
subclasses.append(rel.get_accessor_name() + LOOKUP_SEP + subclass)
|
subclasses.append(
|
||||||
|
rel.get_accessor_name() + LOOKUP_SEP + subclass)
|
||||||
subclasses.append(rel.get_accessor_name())
|
subclasses.append(rel.get_accessor_name())
|
||||||
return subclasses
|
return subclasses
|
||||||
|
|
||||||
|
|
||||||
def _get_ancestors_path(self, model, levels=None):
|
def _get_ancestors_path(self, model, levels=None):
|
||||||
"""
|
"""
|
||||||
Serves as an opposite to _get_subclasses_recurse, instead walking from
|
Serves as an opposite to _get_subclasses_recurse, instead walking from
|
||||||
|
|
@ -127,23 +124,27 @@ class InheritanceQuerySetMixin(object):
|
||||||
select_related string backwards.
|
select_related string backwards.
|
||||||
"""
|
"""
|
||||||
if not issubclass(model, self.model):
|
if not issubclass(model, self.model):
|
||||||
raise ValueError("%r is not a subclass of %r" % (model, self.model))
|
raise ValueError(
|
||||||
|
"%r is not a subclass of %r" % (model, self.model))
|
||||||
|
|
||||||
ancestry = []
|
ancestry = []
|
||||||
# should be a OneToOneField or None
|
# should be a OneToOneField or None
|
||||||
parent = model._meta.get_ancestor_link(self.model)
|
parent_link = model._meta.get_ancestor_link(self.model)
|
||||||
if levels:
|
if levels:
|
||||||
levels -= 1
|
levels -= 1
|
||||||
while parent is not None:
|
while parent_link is not None:
|
||||||
ancestry.insert(0, parent.related.get_accessor_name())
|
ancestry.insert(0, parent_link.related.get_accessor_name())
|
||||||
if levels or levels is None:
|
if levels or levels is None:
|
||||||
parent = parent.related.parent_model._meta.get_ancestor_link(
|
if django.VERSION < (1, 8):
|
||||||
|
parent_model = parent_link.related.parent_model
|
||||||
|
else:
|
||||||
|
parent_model = parent_link.related.model
|
||||||
|
parent_link = parent_model._meta.get_ancestor_link(
|
||||||
self.model)
|
self.model)
|
||||||
else:
|
else:
|
||||||
parent = None
|
parent_link = None
|
||||||
return LOOKUP_SEP.join(ancestry)
|
return LOOKUP_SEP.join(ancestry)
|
||||||
|
|
||||||
|
|
||||||
def _get_sub_obj_recurse(self, obj, s):
|
def _get_sub_obj_recurse(self, obj, s):
|
||||||
rel, _, s = s.partition(LOOKUP_SEP)
|
rel, _, s = s.partition(LOOKUP_SEP)
|
||||||
try:
|
try:
|
||||||
|
|
@ -170,6 +171,7 @@ class InheritanceQuerySetMixin(object):
|
||||||
levels = 1
|
levels = 1
|
||||||
return levels
|
return levels
|
||||||
|
|
||||||
|
|
||||||
class InheritanceManagerMixin(object):
|
class InheritanceManagerMixin(object):
|
||||||
use_for_related_fields = True
|
use_for_related_fields = True
|
||||||
|
|
||||||
|
|
@ -188,6 +190,7 @@ class InheritanceManagerMixin(object):
|
||||||
class InheritanceQuerySet(InheritanceQuerySetMixin, QuerySet):
|
class InheritanceQuerySet(InheritanceQuerySetMixin, QuerySet):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class InheritanceManager(InheritanceManagerMixin, models.Manager):
|
class InheritanceManager(InheritanceManagerMixin, models.Manager):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
@ -271,7 +274,8 @@ class PassThroughManagerMixin(object):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def for_queryset_class(cls, queryset_cls):
|
def for_queryset_class(cls, queryset_cls):
|
||||||
return create_pass_through_manager_for_queryset_class(cls, queryset_cls)
|
return create_pass_through_manager_for_queryset_class(
|
||||||
|
cls, queryset_cls)
|
||||||
|
|
||||||
|
|
||||||
class PassThroughManager(PassThroughManagerMixin, models.Manager):
|
class PassThroughManager(PassThroughManagerMixin, models.Manager):
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue