Added a change to get_objs_with_attr_values that means simple python lookup values will be searched for directly in the database by pickling the input argument in the form used by Attributes. This should lead to a more efficient attrvalue lookup for larger databases (as long as value is a string, int or float and not a compound object, at which the lookup is continuously done in two steps filtering through the Attribute value mechanism.

This commit is contained in:
Griatch 2012-09-28 00:02:31 +02:00
parent 14cc2e0f97
commit c819cdc2a6

View file

@ -1,6 +1,8 @@
""" """
Custom manager for Objects. Custom manager for Objects.
""" """
try: import cPickle as pickle
except ImportError: import pickle
from django.db.models import Q from django.db.models import Q
from django.conf import settings from django.conf import settings
#from django.contrib.auth.models import User #from django.contrib.auth.models import User
@ -8,10 +10,11 @@ from django.db.models.fields import exceptions
from src.typeclasses.managers import TypedObjectManager from src.typeclasses.managers import TypedObjectManager
from src.typeclasses.managers import returns_typeclass, returns_typeclass_list from src.typeclasses.managers import returns_typeclass, returns_typeclass_list
from src.utils import utils from src.utils import utils
from src.utils.utils import to_unicode, make_iter, string_partial_matching from src.utils.utils import to_unicode, make_iter, string_partial_matching, to_str
__all__ = ("ObjectManager",) __all__ = ("ObjectManager",)
_GA = object.__getattribute__ _GA = object.__getattribute__
_DUMPS = lambda inp: to_unicode(pickle.dumps(inp))
# Try to use a custom way to parse id-tagged multimatches. # Try to use a custom way to parse id-tagged multimatches.
@ -126,6 +129,11 @@ class ObjectManager(TypedObjectManager):
not make sense to offer an "exact" type matching for this. not make sense to offer an "exact" type matching for this.
""" """
cand_restriction = candidates and Q(db_obj__pk__in=[_GA(obj, "id") for obj in make_iter(candidates) if obj]) or Q() cand_restriction = candidates and Q(db_obj__pk__in=[_GA(obj, "id") for obj in make_iter(candidates) if obj]) or Q()
if type(attribute_value) in (basestring, int, float):
# simple attribute_value - do direct lookup
return self.model.objattribute_set.related.model.objects.select_related("db_obj").filter(cand_restriction & Q(db_key=attribute_name) & Q(db_value=_DUMPS(("simple", attribute_value))))
else:
# go via attribute conversion
attrs= self.model.objattribute_set.related.model.objects.select_related("db_obj").filter(cand_restriction & Q(db_key=attribute_name)) attrs= self.model.objattribute_set.related.model.objects.select_related("db_obj").filter(cand_restriction & Q(db_key=attribute_name))
return [attr.db_obj for attr in attrs if attribute_value == attr.value] return [attr.db_obj for attr in attrs if attribute_value == attr.value]