@@ -53,37 +53,36 @@ def __iter__(self):
53
53
compiler = connection .ops .compiler ("SQLCompiler" )(query , connection , db )
54
54
query_iterator = iter (query )
55
55
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 :
80
58
# 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
87
86
finally :
88
87
query .cursor .close ()
89
88
@@ -93,4 +92,5 @@ def _make_result(self, query):
93
92
of __iter__().
94
93
"""
95
94
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