summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoulder Sprinters <boulder-sprinters@djangoproject.com>2007-06-01 00:22:18 +0000
committerBoulder Sprinters <boulder-sprinters@djangoproject.com>2007-06-01 00:22:18 +0000
commit959343fc7e7f1b5c2e58a7890c848c172ad1fbbe (patch)
treead90480372c2c48c758157a12fd61992a6f621ff
parentbc8d41974dfd8097e6296c9706883306d8dd013a (diff)
downloaddjango-959343fc7e7f1b5c2e58a7890c848c172ad1fbbe.tar.gz
boulder-oracle-sprint: Merged [5385]. It got missed earlier.
git-svn-id: http://code.djangoproject.com/svn/django/branches/boulder-oracle-sprint@5396 bcc190cf-cafb-0310-a4f2-bffc1f526a37
-rw-r--r--django/db/models/query.py23
-rw-r--r--tests/modeltests/lookup/models.py21
2 files changed, 39 insertions, 5 deletions
diff --git a/django/db/models/query.py b/django/db/models/query.py
index e3b9c794f8..40a110129e 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -566,9 +566,8 @@ else:
class ValuesQuerySet(QuerySet):
def __init__(self, *args, **kwargs):
super(ValuesQuerySet, self).__init__(*args, **kwargs)
- # select_related and select aren't supported in values().
+ # select_related isn't supported in values().
self._select_related = False
- self._select = {}
def iterator(self):
try:
@@ -578,13 +577,27 @@ class ValuesQuerySet(QuerySet):
# self._fields is a list of field names to fetch.
if self._fields:
- fields = [self.model._meta.get_field(f, many_to_many=False) for f in self._fields]
+ if not self._select:
+ fields = [self.model._meta.get_field(f, many_to_many=False) for f in self._fields]
+ else:
+ fields = []
+ for f in self._fields:
+ if f in [field.name for field in self.model._meta.fields]:
+ fields.append(self.model._meta.get_field(f, many_to_many=False))
+ elif not self._select.has_key( f ):
+ raise FieldDoesNotExist, '%s has no field named %r' % ( self.model._meta.object_name, f )
+
+ field_names = self._fields
else: # Default to all fields.
fields = self.model._meta.fields
- columns = [f.column for f in fields]
- field_names = [f.attname for f in fields]
+ field_names = [f.attname for f in fields]
+ columns = [f.column for f in fields]
select = ['%s.%s' % (backend.quote_name(self.model._meta.db_table), backend.quote_name(c)) for c in columns]
+ # Add any additional SELECTs.
+ if self._select:
+ select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), backend.quote_name(s[0])) for s in self._select.items()])
+
cursor = connection.cursor()
cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params)
diff --git a/tests/modeltests/lookup/models.py b/tests/modeltests/lookup/models.py
index c634aef8a1..6af70f8351 100644
--- a/tests/modeltests/lookup/models.py
+++ b/tests/modeltests/lookup/models.py
@@ -131,6 +131,27 @@ True
[('headline', 'Article 7'), ('id', 7)]
[('headline', 'Article 1'), ('id', 1)]
+
+# you can use values() even on extra fields
+>>> for d in Article.objects.extra( select={'id_plus_one' : 'id + 1'} ).values('id', 'id_plus_one'):
+... i = d.items()
+... i.sort()
+... i
+[('id', 5), ('id_plus_one', 6)]
+[('id', 6), ('id_plus_one', 7)]
+[('id', 4), ('id_plus_one', 5)]
+[('id', 2), ('id_plus_one', 3)]
+[('id', 3), ('id_plus_one', 4)]
+[('id', 7), ('id_plus_one', 8)]
+[('id', 1), ('id_plus_one', 2)]
+
+# however, an exception FieldDoesNotExist will still be thrown
+# if you try to access non-existent field (field that is neither on the model nor extra)
+>>> Article.objects.extra( select={'id_plus_one' : 'id + 1'} ).values('id', 'id_plus_two')
+Traceback (most recent call last):
+ ...
+FieldDoesNotExist: Article has no field named 'id_plus_two'
+
# if you don't specify which fields, all are returned
>>> list(Article.objects.filter(id=5).values()) == [{'id': 5, 'headline': 'Article 5', 'pub_date': datetime(2005, 8, 1, 9, 0)}]
True