Code

Ticket #3050: values-5383.diff

File values-5383.diff, 3.4 KB (added by Honza Král <Honza.Kral@…>, 7 years ago)

updated for current trunk (revision 5383)

Line 
1Index: django/db/models/query.py
2===================================================================
3--- django/db/models/query.py   (revision 5383)
4+++ django/db/models/query.py   (working copy)
5@@ -554,9 +554,8 @@
6 class ValuesQuerySet(QuerySet):
7     def __init__(self, *args, **kwargs):
8         super(ValuesQuerySet, self).__init__(*args, **kwargs)
9-        # select_related and select aren't supported in values().
10+        # select_related isn't supported in values().
11         self._select_related = False
12-        self._select = {}
13 
14     def iterator(self):
15         try:
16@@ -566,13 +565,28 @@
17 
18         # self._fields is a list of field names to fetch.
19         if self._fields:
20-            columns = [self.model._meta.get_field(f, many_to_many=False).column for f in self._fields]
21+            #columns = [self.model._meta.get_field(f, many_to_many=False).column for f in self._fields]
22+            if not self._select:
23+                columns = [self.model._meta.get_field(f, many_to_many=False).column for f in self._fields]
24+            else:
25+                columns = []
26+                for f in self._fields:
27+                    if f in [field.name for field in self.model._meta.fields]:
28+                        columns.append( self.model._meta.get_field(f, many_to_many=False).column )
29+                    elif not self._select.has_key( f ):
30+                        raise FieldDoesNotExist, '%s has no field named %r' % ( self.model._meta.object_name, f )
31+
32             field_names = self._fields
33         else: # Default to all fields.
34             columns = [f.column for f in self.model._meta.fields]
35             field_names = [f.attname for f in self.model._meta.fields]
36 
37         select = ['%s.%s' % (backend.quote_name(self.model._meta.db_table), backend.quote_name(c)) for c in columns]
38+
39+        # Add any additional SELECTs.
40+        if self._select:
41+            select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), backend.quote_name(s[0])) for s in self._select.items()])
42+
43         cursor = connection.cursor()
44         cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params)
45         while 1:
46Index: tests/modeltests/lookup/models.py
47===================================================================
48--- tests/modeltests/lookup/models.py   (revision 5383)
49+++ tests/modeltests/lookup/models.py   (working copy)
50@@ -131,6 +131,27 @@
51 [('headline', 'Article 7'), ('id', 7)]
52 [('headline', 'Article 1'), ('id', 1)]
53 
54+
55+# you can use values() even on extra fields
56+>>> for d in Article.objects.extra( select={'id_plus_one' : 'id + 1'} ).values('id', 'id_plus_one'):
57+...     i = d.items()
58+...     i.sort()
59+...     i
60+[('id', 5), ('id_plus_one', 6)]
61+[('id', 6), ('id_plus_one', 7)]
62+[('id', 4), ('id_plus_one', 5)]
63+[('id', 2), ('id_plus_one', 3)]
64+[('id', 3), ('id_plus_one', 4)]
65+[('id', 7), ('id_plus_one', 8)]
66+[('id', 1), ('id_plus_one', 2)]
67+
68+# however, an exception FieldDoesNotExist will still be thrown
69+# if you try to access non-existent field (field that is neither on the model nor extra)
70+>>> Article.objects.extra( select={'id_plus_one' : 'id + 1'} ).values('id', 'id_plus_two')
71+Traceback (most recent call last):
72+    ...
73+FieldDoesNotExist: Article has no field named 'id_plus_two'
74+
75 # if you don't specify which fields, all are returned
76 >>> list(Article.objects.filter(id=5).values()) == [{'id': 5, 'headline': 'Article 5', 'pub_date': datetime(2005, 8, 1, 9, 0)}]
77 True