summaryrefslogtreecommitdiff
path: root/django/db/models/query.py
diff options
context:
space:
mode:
authorRussell Keith-Magee <russell@keith-magee.com>2009-02-16 12:28:37 +0000
committerRussell Keith-Magee <russell@keith-magee.com>2009-02-16 12:28:37 +0000
commit58ea6d45618cb8b5bd4306c395d7bb8860f9a842 (patch)
tree62c4bfe83ecff6ed7e5a7c0d8d1ef9d17803f127 /django/db/models/query.py
parent88837875f245672a5e8671a1d144c78d3e102450 (diff)
Fixed #10256 -- Corrected the interaction of extra(select=) with values() and values_list() where an explicit list of columns is requested.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@9837 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/db/models/query.py')
-rw-r--r--django/db/models/query.py52
1 files changed, 34 insertions, 18 deletions
diff --git a/django/db/models/query.py b/django/db/models/query.py
index c06a37897e..86fafc519d 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -727,12 +727,15 @@ class ValuesQuerySet(QuerySet):
# names of the model fields to select.
def iterator(self):
- if (not self.extra_names and
- len(self.field_names) != len(self.model._meta.fields)):
+ # Purge any extra columns that haven't been explicitly asked for
+ if self.extra_names is not None:
self.query.trim_extra_select(self.extra_names)
- names = self.query.extra_select.keys() + self.field_names
- names.extend(self.query.aggregate_select.keys())
+ extra_names = self.query.extra_select.keys()
+ field_names = self.field_names
+ aggregate_names = self.query.aggregate_select.keys()
+
+ names = extra_names + field_names + aggregate_names
for row in self.query.results_iter():
yield dict(zip(names, row))
@@ -745,29 +748,30 @@ class ValuesQuerySet(QuerySet):
instance.
"""
self.query.clear_select_fields()
- self.extra_names = []
- self.aggregate_names = []
if self._fields:
+ self.extra_names = []
+ self.aggregate_names = []
if not self.query.extra_select and not self.query.aggregate_select:
- field_names = list(self._fields)
+ self.field_names = list(self._fields)
else:
- field_names = []
+ self.query.default_cols = False
+ self.field_names = []
for f in self._fields:
if self.query.extra_select.has_key(f):
self.extra_names.append(f)
elif self.query.aggregate_select.has_key(f):
self.aggregate_names.append(f)
else:
- field_names.append(f)
+ self.field_names.append(f)
else:
# Default to all fields.
- field_names = [f.attname for f in self.model._meta.fields]
+ self.extra_names = None
+ self.field_names = [f.attname for f in self.model._meta.fields]
+ self.aggregate_names = None
self.query.select = []
- self.query.add_fields(field_names, False)
- self.query.default_cols = False
- self.field_names = field_names
+ self.query.add_fields(self.field_names, False)
def _clone(self, klass=None, setup=False, **kwargs):
"""
@@ -817,7 +821,8 @@ class ValuesQuerySet(QuerySet):
class ValuesListQuerySet(ValuesQuerySet):
def iterator(self):
- self.query.trim_extra_select(self.extra_names)
+ if self.extra_names is not None:
+ self.query.trim_extra_select(self.extra_names)
if self.flat and len(self._fields) == 1:
for row in self.query.results_iter():
yield row[0]
@@ -825,13 +830,24 @@ class ValuesListQuerySet(ValuesQuerySet):
for row in self.query.results_iter():
yield tuple(row)
else:
- # When extra(select=...) is involved, the extra cols come are
- # always at the start of the row, so we need to reorder the fields
+ # When extra(select=...) or an annotation is involved, the extra cols are
+ # always at the start of the row, and we need to reorder the fields
# to match the order in self._fields.
- names = self.query.extra_select.keys() + self.field_names + self.query.aggregate_select.keys()
+ extra_names = self.query.extra_select.keys()
+ field_names = self.field_names
+ aggregate_names = self.query.aggregate_select.keys()
+ names = extra_names + field_names + aggregate_names
+
+ # If a field list has been specified, use it. Otherwise, use the
+ # full list of fields, including extras and aggregates.
+ if self._fields:
+ fields = self._fields
+ else:
+ fields = names
+
for row in self.query.results_iter():
data = dict(zip(names, row))
- yield tuple([data[f] for f in self._fields])
+ yield tuple([data[f] for f in fields])
def _clone(self, *args, **kwargs):
clone = super(ValuesListQuerySet, self)._clone(*args, **kwargs)