From e49a09731bfd2bab46b8f019c23ce96f70c0ad71 Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Mon, 30 Jan 2006 05:38:02 +0000 Subject: [PATCH] magic-removal: Implemented QuerySet.values(). All 'lookup' unit tests pass. git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@2181 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/db/models/manager.py | 25 ------------------------- django/db/models/query.py | 21 +++++++++++++++++++++ tests/modeltests/lookup/models.py | 14 ++++++-------- 3 files changed, 27 insertions(+), 33 deletions(-) diff --git a/django/db/models/manager.py b/django/db/models/manager.py index 581ced8dc4..662e342af6 100644 --- a/django/db/models/manager.py +++ b/django/db/models/manager.py @@ -43,31 +43,6 @@ class Manager(QuerySet): if not hasattr(klass, '_default_manager') or self.creation_counter < klass._default_manager.creation_counter: klass._default_manager = self - def get_values_iterator(self, *args, **kwargs): - # select_related and select aren't supported in get_values(). - kwargs['select_related'] = False - kwargs['select'] = {} - - # 'fields' is a list of field names to fetch. - try: - fields = [self.klass._meta.get_field(f).column for f in kwargs.pop('fields')] - except KeyError: # Default to all fields. - fields = [f.column for f in self.klass._meta.fields] - - cursor = connection.cursor() - _, sql, params = self._get_sql_clause(True, *args, **kwargs) - select = ['%s.%s' % (backend.quote_name(self.klass._meta.db_table), backend.quote_name(f)) for f in fields] - cursor.execute("SELECT " + (kwargs.get('distinct') and "DISTINCT " or "") + ",".join(select) + sql, params) - while 1: - rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE) - if not rows: - raise StopIteration - for row in rows: - yield dict(zip(fields, row)) - - def get_values(self, *args, **kwargs): - return list(self.get_values_iterator(*args, **kwargs)) - def __get_latest(self, *args, **kwargs): kwargs['order_by'] = ('-' + self.klass._meta.get_latest_by,) kwargs['limit'] = 1 diff --git a/django/db/models/query.py b/django/db/models/query.py index 0e45924e24..11de161bbb 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -188,6 +188,27 @@ class QuerySet(object): bulk_query._params.extend(id_list) return dict([(obj._get_pk_val(), obj) for obj in bulk_query.iterator()]) + def values(self, *fields): + # select_related and select aren't supported in values(). + values_query = self._clone(_select_related=False, _select={}) + + # 'fields' is a list of field names to fetch. + if fields: + columns = [self.klass._meta.get_field(f, many_to_many=False).column for f in fields] + else: # Default to all fields. + columns = [f.column for f in self.klass._meta.fields] + + cursor = connection.cursor() + select, sql, params = values_query._get_sql_clause(True) + select = ['%s.%s' % (backend.quote_name(self.klass._meta.db_table), backend.quote_name(c)) for c in columns] + cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params) + while 1: + rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE) + if not rows: + raise StopIteration + for row in rows: + yield dict(zip(fields, row)) + def dates(self, field_name, kind, order='ASC'): """ Returns a list of datetime objects representing all available dates diff --git a/tests/modeltests/lookup/models.py b/tests/modeltests/lookup/models.py index 60235c019d..acbe1fd1bd 100644 --- a/tests/modeltests/lookup/models.py +++ b/tests/modeltests/lookup/models.py @@ -82,18 +82,16 @@ Traceback (most recent call last): ... TypeError: in_bulk() got an unexpected keyword argument 'headline__startswith' -# get_values() is just like get_list(), except it returns a list of -# dictionaries instead of object instances -- and you can specify which fields -# you want to retrieve. ->>> Article.objects.get_values(fields=['headline']) +# values() returns a list of dictionaries instead of object instances -- and +# you can specify which fields you want to retrieve. +>>> list(Article.objects.values('headline')) [{'headline': 'Article 5'}, {'headline': 'Article 6'}, {'headline': 'Article 4'}, {'headline': 'Article 2'}, {'headline': 'Article 3'}, {'headline': 'Article 7'}, {'headline': 'Article 1'}] ->>> Article.objects.get_values(pub_date__exact=datetime(2005, 7, 27), fields=['id']) +>>> list(Article.objects.filter(pub_date__exact=datetime(2005, 7, 27)).values('id')) [{'id': 2}, {'id': 3}, {'id': 7}] ->>> Article.objects.get_values(fields=['id', 'headline']) == [{'id': 5, 'headline': 'Article 5'}, {'id': 6, 'headline': 'Article 6'}, {'id': 4, 'headline': 'Article 4'}, {'id': 2, 'headline': 'Article 2'}, {'id': 3, 'headline': 'Article 3'}, {'id': 7, 'headline': 'Article 7'}, {'id': 1, 'headline': 'Article 1'}] +>>> list(Article.objects.values('id', 'headline')) == [{'id': 5, 'headline': 'Article 5'}, {'id': 6, 'headline': 'Article 6'}, {'id': 4, 'headline': 'Article 4'}, {'id': 2, 'headline': 'Article 2'}, {'id': 3, 'headline': 'Article 3'}, {'id': 7, 'headline': 'Article 7'}, {'id': 1, 'headline': 'Article 1'}] True -# get_values_iterator() is just like get_values(), but it's a generator. ->>> for d in Article.objects.get_values_iterator(fields=['id', 'headline']): +>>> for d in Article.objects.values('id', 'headline'): ... i = d.items() ... i.sort() ... i