Ticket #14930: extra_order_by_values_list-with_test-2.diff

File extra_order_by_values_list-with_test-2.diff, 3.7 KB (added by vicould, 3 years ago)

Improved patch

  • django/db/models/query.py

    diff --git a/django/db/models/query.py b/django/db/models/query.py
    index 0210a79..0d87ea9 100644
    a b class ValuesQuerySet(QuerySet): 
    980980
    981981        names = extra_names + field_names + aggregate_names
    982982
     983        # If a field list has been specified, use it. Otherwise, use the
     984        # full list of fields, including extras and aggregates.
     985        if self._fields:
     986            fields = list(self._fields) + [f for f in aggregate_names if f not in self._fields]
     987        else:
     988            fields = names
     989
    983990        for row in self.query.get_compiler(self.db).results_iter():
    984             yield dict(zip(names, row))
     991            # removes the non-necessary fields in the intersection
     992            # between names and fields
     993            yield {key: elem for key, elem in zip(names, row) if key in fields}
    985994
    986995    def _setup_query(self):
    987996        """
    class ValuesQuerySet(QuerySet): 
    10211030            self.aggregate_names = None
    10221031
    10231032        self.query.select = []
    1024         if self.extra_names is not None:
    1025             self.query.set_extra_mask(self.extra_names)
     1033        extra_mask_names = list(self.extra_names or []) + list(self.query.extra_order_by or [])
     1034        if extra_mask_names:
     1035            self.query.set_extra_mask(extra_mask_names)
    10261036        self.query.add_fields(self.field_names, True)
    10271037        if self.aggregate_names is not None:
    10281038            self.query.set_aggregate_mask(self.aggregate_names)
    class ValuesListQuerySet(ValuesQuerySet): 
    10971107    def iterator(self):
    10981108        if self.flat and len(self._fields) == 1:
    10991109            for row in self.query.get_compiler(self.db).results_iter():
    1100                 yield row[0]
     1110                yield row[len(self.query.extra_select_mask or [])]
    11011111        elif not self.query.extra_select and not self.query.aggregate_select:
    11021112            for row in self.query.get_compiler(self.db).results_iter():
    11031113                yield tuple(row)
  • tests/regressiontests/queries/tests.py

    diff --git a/tests/regressiontests/queries/tests.py b/tests/regressiontests/queries/tests.py
    index 71ac107..0a3d23f 100644
    a b class Queries5Tests(TestCase): 
    12801280        # An empty values() call includes all aliases, including those from an
    12811281        # extra()
    12821282        qs = Ranking.objects.extra(select={'good': 'case when rank > 2 then 1 else 0 end'})
    1283         dicts = qs.values().order_by('id')
     1283        dicts = qs.values()
     1284        dicts = dicts.order_by('id')
    12841285        for d in dicts: del d['id']; del d['author_id']
    12851286        self.assertEqual(
    12861287            [sorted(d.items()) for d in dicts],
    class EmptyQuerySetTests(TestCase): 
    17001701
    17011702
    17021703class ValuesQuerysetTests(BaseQuerysetTest):
    1703     def test_flat_values_lits(self):
     1704    def setUp(self):
    17041705        Number.objects.create(num=72)
     1706
     1707    def test_flat_values_lits(self):
    17051708        qs = Number.objects.values_list("num")
    17061709        qs = qs.values_list("num", flat=True)
    17071710        self.assertValueQuerysetEqual(
    17081711            qs, [72]
    17091712        )
    17101713
     1714    def test_extra_values(self):
     1715        # testing for ticket 14930 issues
     1716        qs = Number.objects.extra(select={'value_plus_one': 'num+1', 'value_minus_one': 'num-1' }).order_by('value_minus_one')
     1717        qs = qs.values('num')
     1718        identity = lambda x:x
     1719        self.assertQuerysetEqual(qs, [{'num': 72}], identity)
     1720
     1721    def test_extra_values_list(self):
     1722        # testing for ticket 14930 issues
     1723        qs = Number.objects.extra(select={'value_plus_one': 'num+1'}).order_by('value_plus_one')
     1724        qs = qs.values_list('num')
     1725        identity = lambda x:x
     1726        self.assertQuerysetEqual(qs, [(72,)], identity)
     1727
    17111728
    17121729class WeirdQuerysetSlicingTests(BaseQuerysetTest):
    17131730    def setUp(self):
Back to Top