@@ -53,37 +53,36 @@ def __iter__(self):
5353 compiler = connection .ops .compiler ("SQLCompiler" )(query , connection , db )
5454 query_iterator = iter (query )
5555 try :
56- # Get the columns from the first result.
57- try :
58- first_result = next (query_iterator )
59- except StopIteration :
60- # No results.
61- return
62- self .queryset .columns = list (first_result .keys ())
63- # Reset the iterator to include the first item.
64- query_iterator = self ._make_result (chain ([first_result ], query_iterator ))
65- (
66- model_init_names ,
67- model_init_pos ,
68- annotation_fields ,
69- ) = self .queryset .resolve_model_init_order ()
70- model_cls = self .queryset .model
71- if model_cls ._meta .pk .attname not in model_init_names :
72- raise FieldDoesNotExist ("Raw query must include the primary key" )
73- fields = [self .queryset .model_fields .get (c ) for c in self .queryset .columns ]
74- converters = compiler .get_converters (
75- [f .get_col (f .model ._meta .db_table ) if f else None for f in fields ]
76- )
77- if converters :
78- query_iterator = compiler .apply_converters (query_iterator , converters )
79- for values in query_iterator :
56+ # Get the columns for each result
57+ for result in query_iterator :
8058 # Associate fields to values
81- model_init_values = [values [pos ] for pos in model_init_pos ]
82- instance = model_cls .from_db (db , model_init_names , model_init_values )
83- if annotation_fields :
84- for column , pos in annotation_fields :
85- setattr (instance , column , values [pos ])
86- yield instance
59+ self .queryset .columns = list (result .keys ())
60+ # Use the new columns to define the new model_init_order.
61+ (
62+ model_init_names ,
63+ model_init_pos ,
64+ annotation_fields ,
65+ ) = self .queryset .resolve_model_init_order ()
66+ model_cls = self .queryset .model
67+ if model_cls ._meta .pk .attname not in model_init_names :
68+ raise FieldDoesNotExist ("Raw query must include the primary key" )
69+ fields = [self .queryset .model_fields .get (c ) for c in self .queryset .columns ]
70+ converters = compiler .get_converters (
71+ [f .get_col (f .model ._meta .db_table ) if f else None for f in fields ]
72+ )
73+ # Make an iterator from the singular result
74+ result_iter = self ._make_result ([result ])
75+ if converters :
76+ result_iter = compiler .apply_converters (result_iter , converters )
77+
78+ # Iterate once to generate a model object based solely on the result
79+ for values in result_iter :
80+ model_init_values = [values [pos ] for pos in model_init_pos ]
81+ instance = model_cls .from_db (db , model_init_names , model_init_values )
82+ if annotation_fields :
83+ for column , pos in annotation_fields :
84+ setattr (instance , column , values [pos ])
85+ yield instance
8786 finally :
8887 query .cursor .close ()
8988
@@ -93,4 +92,5 @@ def _make_result(self, query):
9392 of __iter__().
9493 """
9594 for result in query :
96- yield tuple (result .values ())
95+ # Create a tuple of values strictly from the outlined result columns
96+ yield tuple (result .get (key , None ) for key in self .queryset .columns )
0 commit comments