Skip to content

Instantly share code, notes, and snippets.

@loic
Created January 16, 2014 16:51
Show Gist options
  • Save loic/8458535 to your computer and use it in GitHub Desktop.
Save loic/8458535 to your computer and use it in GitHub Desktop.
diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
index 82e7725..a874b3a 100644
--- a/django/db/models/fields/related.py
+++ b/django/db/models/fields/related.py
@@ -173,21 +173,24 @@ class SingleRelatedObjectDescriptor(six.with_metaclass(RenameRelatedObjectDescri
return self.related.model._base_manager.db_manager(hints=hints)
def get_prefetch_queryset(self, instances, queryset=None):
- if queryset is not None:
- raise ValueError("Custom queryset can't be used for this lookup.")
+ if queryset is None:
+ queryset = self.get_queryset().all()
+ queryset._add_hints(instance=instances[0])
rel_obj_attr = attrgetter(self.related.field.attname)
instance_attr = lambda obj: obj._get_pk_val()
instances_dict = dict((instance_attr(inst), inst) for inst in instances)
query = {'%s__in' % self.related.field.name: instances}
- qs = self.get_queryset(instance=instances[0]).filter(**query)
+
+ queryset = queryset.filter(**query)
+
# Since we're going to assign directly in the cache,
# we must manage the reverse relation cache manually.
rel_obj_cache_name = self.related.field.get_cache_name()
- for rel_obj in qs:
+ for rel_obj in queryset:
instance = instances_dict[rel_obj_attr(rel_obj)]
setattr(rel_obj, rel_obj_cache_name, instance)
- return qs, rel_obj_attr, instance_attr, True, self.cache_name
+ return queryset, rel_obj_attr, instance_attr, True, self.cache_name
def __get__(self, instance, instance_type=None):
if instance is None:
@@ -303,8 +306,9 @@ class ReverseSingleRelatedObjectDescriptor(six.with_metaclass(RenameRelatedObjec
return QuerySet(self.field.rel.to, hints=hints)
def get_prefetch_queryset(self, instances, queryset=None):
- if queryset is not None:
- raise ValueError("Custom queryset can't be used for this lookup.")
+ if queryset is None:
+ queryset = self.get_queryset().all()
+ queryset._add_hints(instance=instances[0])
rel_obj_attr = self.field.get_foreign_related_value
instance_attr = self.field.get_local_related_value
@@ -319,16 +323,16 @@ class ReverseSingleRelatedObjectDescriptor(six.with_metaclass(RenameRelatedObjec
query = {'%s__in' % related_field.name: set(instance_attr(inst)[0] for inst in instances)}
else:
query = {'%s__in' % self.field.related_query_name(): instances}
+ queryset = queryset.filter(**query)
- qs = self.get_queryset(instance=instances[0]).filter(**query)
# Since we're going to assign directly in the cache,
# we must manage the reverse relation cache manually.
if not self.field.rel.multiple:
rel_obj_cache_name = self.field.related.get_cache_name()
- for rel_obj in qs:
+ for rel_obj in queryset:
instance = instances_dict[rel_obj_attr(rel_obj)]
setattr(rel_obj, rel_obj_cache_name, instance)
- return qs, rel_obj_attr, instance_attr, True, self.cache_name
+ return queryset, rel_obj_attr, instance_attr, True, self.cache_name
def __get__(self, instance, instance_type=None):
if instance is None:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment