Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

queryset-refactor: Added valuelist() method to querysets. Refs #2482.

git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@7149 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit cbd6da3540e1116e6d049c2affd9f6894f427ace 1 parent 6ad9c68
Malcolm Tredinnick authored February 23, 2008
3  django/db/models/manager.py
@@ -101,6 +101,9 @@ def select_related(self, *args, **kwargs):
101 101
     def values(self, *args, **kwargs):
102 102
         return self.get_query_set().values(*args, **kwargs)
103 103
 
  104
+    def valueslist(self, *args, **kwargs):
  105
+        return self.get_query_set().valueslist(*args, **kwargs)
  106
+
104 107
     def update(self, *args, **kwargs):
105 108
         return self.get_query_set().update(*args, **kwargs)
106 109
 
25  django/db/models/query.py
@@ -278,6 +278,16 @@ def update(self, **kwargs):
278 278
     def values(self, *fields):
279 279
         return self._clone(klass=ValuesQuerySet, setup=True, _fields=fields)
280 280
 
  281
+    def valueslist(self, *fields, **kwargs):
  282
+        flat = kwargs.pop('flat', False)
  283
+        if kwargs:
  284
+            raise TypeError('Unexpected keyword arguments to valueslist: %s'
  285
+                    % (kwargs.keys(),))
  286
+        if flat and len(fields) > 1:
  287
+            raise TypeError("'flat' is not valid when valueslist is called with more than one field.")
  288
+        return self._clone(klass=ValuesListQuerySet, setup=True, flat=flat,
  289
+                _fields=fields)
  290
+
281 291
     def dates(self, field_name, kind, order='ASC'):
282 292
         """
283 293
         Returns a list of datetime objects representing all available dates
@@ -531,6 +541,21 @@ def _clone(self, klass=None, setup=False, **kwargs):
531 541
             c._setup_query()
532 542
         return c
533 543
 
  544
+class ValuesListQuerySet(ValuesQuerySet):
  545
+    def iterator(self):
  546
+        self.field_names.extend([f for f in self.query.extra_select.keys()])
  547
+        if self.flat and len(self._fields) == 1:
  548
+            for row in self.query.results_iter():
  549
+                yield row[0]
  550
+        else:
  551
+            for row in self.query.results_iter():
  552
+                yield row
  553
+
  554
+    def _clone(self, *args, **kwargs):
  555
+        clone = super(ValuesListQuerySet, self)._clone(*args, **kwargs)
  556
+        clone.flat = self.flat
  557
+        return clone
  558
+
534 559
 class DateQuerySet(QuerySet):
535 560
     def iterator(self):
536 561
         return self.query.results_iter()
28  docs/db-api.txt
@@ -664,6 +664,34 @@ followed (optionally) by any output-affecting methods (such as ``values()``),
664 664
 but it doesn't really matter. This is your chance to really flaunt your
665 665
 individualism.
666 666
 
  667
+``valueslist(*fields)``
  668
+~~~~~~~~~~~~~~~~~~~~~~~
  669
+
  670
+**New in Django development version**
  671
+
  672
+This is similar to ``values()`` except that instead of returning a list of
  673
+dictionaries, it returns a list of tuples. Each tuple contains the value from
  674
+the respective field passed into the ``valueslist()`` call -- so the first
  675
+item is the first field, etc. For example::
  676
+
  677
+    >>> Entry.objects.valueslist('id', 'headling')
  678
+    [(1, u'First entry'), ...]
  679
+
  680
+If you only pass in a single field, you can also pass in the ``flat``
  681
+parameter. If ``True``, this will mean the returned results are single values,
  682
+rather than one-tuples. An example should make the difference clearer::
  683
+
  684
+    >>> Entry.objects.valueslist('id').order_by('id')
  685
+    [(1,), (2,), (3,), ...]
  686
+
  687
+    >>> Entry.objects.valueslist('id', flat=True).order_by('id')
  688
+    [1, 2, 3, ...]
  689
+
  690
+It is an error to pass in ``flat`` when there is more than one field.
  691
+
  692
+If you don't pass any values to ``valueslist()``, it will return all the
  693
+fields in the model, in the order they were declared.
  694
+
667 695
 ``dates(field, kind, order='ASC')``
668 696
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
669 697
 
17  tests/modeltests/lookup/models.py
@@ -165,6 +165,23 @@ def __unicode__(self):
165 165
 >>> list(Article.objects.filter(id=5).values()) == [{'id': 5, 'headline': 'Article 5', 'pub_date': datetime(2005, 8, 1, 9, 0)}]
166 166
 True
167 167
 
  168
+# valueslist() is similar to values(), except that the results are returned as
  169
+# a list of tuples, rather than a list of dictionaries. Within each tuple, the
  170
+# order of the elemnts is the same as the order of fields in the valueslist()
  171
+# call.
  172
+>>> Article.objects.valueslist('headline')
  173
+[(u'Article 5',), (u'Article 6',), (u'Article 4',), (u'Article 2',), (u'Article 3',), (u'Article 7',), (u'Article 1',)]
  174
+
  175
+>>> Article.objects.valueslist('id').order_by('id')
  176
+[(1,), (2,), (3,), (4,), (5,), (6,), (7,)]
  177
+>>> Article.objects.valueslist('id', flat=True).order_by('id')
  178
+[1, 2, 3, 4, 5, 6, 7]
  179
+
  180
+>>> Article.objects.valueslist('id', 'headline', flat=True)
  181
+Traceback (most recent call last):
  182
+...
  183
+TypeError: 'flat' is not valid when valueslist is called with more than one field.
  184
+
168 185
 # Every DateField and DateTimeField creates get_next_by_FOO() and
169 186
 # get_previous_by_FOO() methods.
170 187
 # In the case of identical date values, these methods will use the ID as a

0 notes on commit cbd6da3

Please sign in to comment.
Something went wrong with that request. Please try again.