Skip to content

Commit

Permalink
Optimised use of 'in' operator on QuerySet using an explicit __contai…
Browse files Browse the repository at this point in the history
…ns__ method.

Without this change, use of 'in' on a QuerySet resulted in ._result_cache
being fully populated, which sometimes is unnecessary work.



git-svn-id: http://code.djangoproject.com/svn/django/trunk@11803 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
spookylukey committed Dec 9, 2009
1 parent bb428f3 commit eeb10d5
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 0 deletions.
30 changes: 30 additions & 0 deletions django/db/models/query.py
Expand Up @@ -107,6 +107,36 @@ def __nonzero__(self):
return False
return True

def __contains__(self, val):
# The 'in' operator works without this method, due to __iter__. This
# implementation exists only to shortcut the creation of Model
# instances, by bailing out early if we find a matching element.
pos = 0
if self._result_cache is not None:
if val in self._result_cache:
return True
elif self._iter is None:
# iterator is exhausted, so we have our answer
return False
# remember not to check these again:
pos = len(self._result_cache)
else:
# We need to start filling the result cache out. The following
# ensures that self._iter is not None and self._result_cache is not
# None
it = iter(self)

# Carry on, one result at a time.
while True:
if len(self._result_cache) <= pos:
self._fill_cache(num=1)
if self._iter is None:
# we ran out of items
return False
if self._result_cache[pos] == val:
return True
pos += 1

def __getitem__(self, k):
"""
Retrieves an item or slice from the set of results.
Expand Down
8 changes: 8 additions & 0 deletions tests/modeltests/basic/models.py
Expand Up @@ -211,6 +211,14 @@ def __unicode__(self):
>>> Article.objects.get(id__exact=8) == Article.objects.get(id__exact=7)
False
# You can use 'in' to test for membership...
>>> a8 in Article.objects.all()
True
# ... but there will often be more efficient ways if that is all you need:
>>> Article.objects.filter(id=a8.id).exists()
True
# dates() returns a list of available dates of the given scope for the given field.
>>> Article.objects.dates('pub_date', 'year')
[datetime.datetime(2005, 1, 1, 0, 0)]
Expand Down

0 comments on commit eeb10d5

Please sign in to comment.