Author: lukeplant Date: 2009-12-09 10:07:21 -0600 (Wed, 09 Dec 2009) New Revision: 11803
Modified: django/trunk/django/db/models/query.py django/trunk/tests/modeltests/basic/models.py Log: 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. Modified: django/trunk/django/db/models/query.py =================================================================== --- django/trunk/django/db/models/query.py 2009-12-09 12:47:50 UTC (rev 11802) +++ django/trunk/django/db/models/query.py 2009-12-09 16:07:21 UTC (rev 11803) @@ -107,6 +107,36 @@ 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. Modified: django/trunk/tests/modeltests/basic/models.py =================================================================== --- django/trunk/tests/modeltests/basic/models.py 2009-12-09 12:47:50 UTC (rev 11802) +++ django/trunk/tests/modeltests/basic/models.py 2009-12-09 16:07:21 UTC (rev 11803) @@ -211,6 +211,14 @@ >>> 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)] -- You received this message because you are subscribed to the Google Groups "Django updates" group. To post to this group, send email to django-upda...@googlegroups.com. To unsubscribe from this group, send email to django-updates+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-updates?hl=en.