From ff7c243b4c1dcefb504b5b636b0631edfb5a46c2 Mon Sep 17 00:00:00 2001 From: Luke Plant Date: Tue, 23 Nov 2010 13:54:58 +0000 Subject: [PATCH] Fixed #14697 - speeded up model instance creation by moving work outside of loops Thanks to akaariai for the report and initial patch. git-svn-id: http://code.djangoproject.com/svn/django/trunk@14687 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/db/models/query.py | 23 ++++++++++++++--------- django/db/models/sql/compiler.py | 3 ++- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/django/db/models/query.py b/django/db/models/query.py index 9b19ec1cafe..d22a1581887 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -266,11 +266,14 @@ class QuerySet(object): init_list.append(field.attname) model_cls = deferred_class_factory(self.model, skip) - compiler = self.query.get_compiler(using=self.db) + # Cache db and model outside the loop + db = self.db + model = self.model + compiler = self.query.get_compiler(using=db) for row in compiler.results_iter(): if fill_cache: - obj, _ = get_cached_row(self.model, row, - index_start, using=self.db, max_depth=max_depth, + obj, _ = get_cached_row(model, row, + index_start, using=db, max_depth=max_depth, requested=requested, offset=len(aggregate_select), only_load=only_load) else: @@ -280,19 +283,21 @@ class QuerySet(object): obj = model_cls(**dict(zip(init_list, row_data))) else: # Omit aggregates in object creation. - obj = self.model(*row[index_start:aggregate_start]) + obj = model(*row[index_start:aggregate_start]) # Store the source database of the object - obj._state.db = self.db + obj._state.db = db # This object came from the database; it's not being added. obj._state.adding = False - for i, k in enumerate(extra_select): - setattr(obj, k, row[i]) + if extra_select: + for i, k in enumerate(extra_select): + setattr(obj, k, row[i]) # Add the aggregates to the model - for i, aggregate in enumerate(aggregate_select): - setattr(obj, aggregate, row[i+aggregate_start]) + if aggregate_select: + for i, aggregate in enumerate(aggregate_select): + setattr(obj, aggregate, row[i+aggregate_start]) yield obj diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py index a11d556b38c..b2249dc607c 100644 --- a/django/db/models/sql/compiler.py +++ b/django/db/models/sql/compiler.py @@ -672,6 +672,7 @@ class SQLCompiler(object): """ resolve_columns = hasattr(self, 'resolve_columns') fields = None + has_aggregate_select = bool(self.query.aggregate_select) for rows in self.execute_sql(MULTI): for row in rows: if resolve_columns: @@ -692,7 +693,7 @@ class SQLCompiler(object): f.column in only_load[db_table]] row = self.resolve_columns(row, fields) - if self.query.aggregate_select: + if has_aggregate_select: aggregate_start = len(self.query.extra_select.keys()) + len(self.query.select) aggregate_end = aggregate_start + len(self.query.aggregate_select) row = tuple(row[:aggregate_start]) + tuple([