Commit eeb10d5f authored by Luke Plant's avatar Luke Plant
Browse files

Optimised use of 'in' operator on QuerySet using an explicit __contains__ 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
parent bb428f3e
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -107,6 +107,36 @@ class QuerySet(object):
            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.
+8 −0
Original line number Diff line number Diff line
@@ -211,6 +211,14 @@ True
>>> 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)]