diff --git a/django/db/models/query.py b/django/db/models/query.py index 2ddcd449cf6..7a81910715f 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -167,17 +167,16 @@ class QuerySet(object): def iterator(self): "Performs the SELECT database lookup of this QuerySet." + try: + select, sql, params = self._get_sql_clause() + except EmptyResultSet: + raise StopIteration + # self._select is a dictionary, and dictionaries' key order is # undefined, so we convert it to a list of tuples. extra_select = self._select.items() cursor = connection.cursor() - - try: - select, sql, params = self._get_sql_clause() - except EmptyResultSet: - raise StopIteration - cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params) fill_cache = self._select_related index_end = len(self.model._meta.fields) @@ -523,11 +522,18 @@ class QuerySet(object): return select, " ".join(sql), params class ValuesQuerySet(QuerySet): - def iterator(self): + def __init__(self, *args, **kwargs): + super(ValuesQuerySet, self).__init__(*args, **kwargs) # select_related and select aren't supported in values(). self._select_related = False self._select = {} + def iterator(self): + try: + select, sql, params = self._get_sql_clause() + except EmptyResultSet: + raise StopIteration + # self._fields is a list of field names to fetch. if self._fields: columns = [self.model._meta.get_field(f, many_to_many=False).column for f in self._fields] @@ -535,15 +541,9 @@ class ValuesQuerySet(QuerySet): else: # Default to all fields. columns = [f.column for f in self.model._meta.fields] field_names = [f.attname for f in self.model._meta.fields] - - cursor = connection.cursor() - - try: - select, sql, params = self._get_sql_clause() - except EmptyResultSet: - raise StopIteration select = ['%s.%s' % (backend.quote_name(self.model._meta.db_table), backend.quote_name(c)) for c in columns] + cursor = connection.cursor() cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params) while 1: rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE) @@ -592,9 +592,6 @@ class EmptyQuerySet(QuerySet): super(EmptyQuerySet, self).__init__(model) self._result_cache = [] - def iterator(self): - raise StopIteration - def count(self): return 0 @@ -606,6 +603,9 @@ class EmptyQuerySet(QuerySet): c._result_cache = [] return c + def _get_sql_clause(self): + raise EmptyResultSet + class QOperator(object): "Base class for QAnd and QOr" def __init__(self, *args): diff --git a/tests/modeltests/lookup/models.py b/tests/modeltests/lookup/models.py index 8468d396f71..d344710befa 100644 --- a/tests/modeltests/lookup/models.py +++ b/tests/modeltests/lookup/models.py @@ -198,6 +198,8 @@ DoesNotExist: Article matching query does not exist. [] >>> Article.objects.none().count() 0 +>>> [article for article in Article.objects.none().iterator()] +[] # using __in with an empty list should return an empty query set >>> Article.objects.filter(id__in=[])