1
1
from functools import reduce , wraps
2
+ from itertools import chain
2
3
from operator import add as add_operator
3
4
4
5
from django .core .exceptions import EmptyResultSet , FieldDoesNotExist , FullResultSet
@@ -387,11 +388,17 @@ def __iter__(self):
387
388
query = self .queryset .query
388
389
connection = connections [db ]
389
390
compiler = connection .ops .compiler ("SQLCompiler" )(query , connection , db )
390
- query_iterator = self ._make_result (query )
391
- # FIXME Get columns from first row of the query without iterating over
392
- # the query.
393
- columns = self .queryset .columns
394
-
391
+ query_iterator = iter (query )
392
+ # Get the columns from the first result.
393
+ try :
394
+ first_item = next (query_iterator )
395
+ except StopIteration :
396
+ # No results.
397
+ query .cursor .close ()
398
+ return
399
+ columns = list (first_item .keys ())
400
+ # Reset the iterator to include the first item.
401
+ query_iterator = self ._make_result (chain ([first_item ], query_iterator ))
395
402
try :
396
403
(
397
404
model_init_names ,
@@ -401,7 +408,7 @@ def __iter__(self):
401
408
model_cls = self .queryset .model
402
409
if model_cls ._meta .pk .attname not in model_init_names :
403
410
raise FieldDoesNotExist ("Raw query must include the primary key" )
404
- fields = [self .queryset .model_fields .get (c ) for c in self . queryset . columns ]
411
+ fields = [self .queryset .model_fields .get (c ) for c in columns ]
405
412
converters = compiler .get_converters (
406
413
[f .get_col (f .model ._meta .db_table ) if f else None for f in fields ]
407
414
)
0 commit comments