Commits

Anonymous committed 54ea998

queryset-refactor: Fixed the interaction between extra(select=...) and
valuelist(). Fixed #7053.

  • Participants
  • Parent commits 06c1bd5
  • Branches queryset-refactor

Comments (0)

Files changed (2)

django/db/models/query.py

 
 class ValuesListQuerySet(ValuesQuerySet):
     def iterator(self):
-        self.field_names.extend([f for f in self.query.extra_select.keys()])
+        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]
-        else:
+        elif not self.query.extra_select:
             for row in self.query.results_iter():
                 yield 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
+            # to match the order in self._fields.
+            names = self.query.extra_select.keys() + self.field_names
+            for row in self.query.results_iter():
+                data = dict(zip(names, row))
+                yield tuple([data[f] for f in self._fields])
 
     def _clone(self, *args, **kwargs):
         clone = super(ValuesListQuerySet, self)._clone(*args, **kwargs)

tests/modeltests/lookup/models.py

 >>> Article.objects.valueslist('id', flat=True).order_by('id')
 [1, 2, 3, 4, 5, 6, 7]
 
+>>> Article.objects.extra(select={'id_plus_one': 'id+1'}).order_by('id').valueslist('id')
+[(1,), (2,), (3,), (4,), (5,), (6,), (7,)]
+>>> Article.objects.extra(select={'id_plus_one': 'id+1'}).order_by('id').valueslist('id_plus_one', 'id')
+[(2, 1), (3, 2), (4, 3), (5, 4), (6, 5), (7, 6), (8, 7)]
+>>> Article.objects.extra(select={'id_plus_one': 'id+1'}).order_by('id').valueslist('id', 'id_plus_one')
+[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8)]
+
 >>> Article.objects.valueslist('id', 'headline', flat=True)
 Traceback (most recent call last):
 ...