Refs -- Added RawModelIterable.
@@ -140,6 +140,50 @@ class ModelIterable(BaseIterable):
yield obj
+class RawModelIterable(BaseIterable):
+ """
+ Iterable that yields a model instance for each row from a raw queryset.
+ """
+
+ def __iter__(self):
+ # Cache some things for performance reasons outside the loop.
+ db = self.queryset.db
+ query = self.queryset.query
+ connection = connections[db]
+ compiler = connection.ops.compiler("SQLCompiler")(query, connection, db)
+ query_iterator = iter(query)
+
+ try:
+ (
+ model_init_names,
+ model_init_pos,
+ annotation_fields,
+ ) = self.queryset.resolve_model_init_order()
+ model_cls = self.queryset.model
+ if model_cls._meta.pk.attname not in model_init_names:
+ raise exceptions.FieldDoesNotExist(
+ "Raw query must include the primary key"
+ )
+ fields = [self.queryset.model_fields.get(c) for c in self.queryset.columns]
+ converters = compiler.get_converters(
+ [f.get_col(f.model._meta.db_table) if f else None for f in fields]
+ )
+ if converters:
+ query_iterator = compiler.apply_converters(query_iterator, converters)
+ for values in query_iterator:
+ # Associate fields to values
+ model_init_values = [values[pos] for pos in model_init_pos]
+ instance = model_cls.from_db(db, model_init_names, model_init_values)
+ if annotation_fields:
+ for column, pos in annotation_fields:
+ setattr(instance, column, values[pos])
+ yield instance
+ finally:
+ # Done iterating the Query. If it has its own cursor, close it.
+ if hasattr(query, "cursor") and query.cursor:
+ query.cursor.close()
+
+
class ValuesIterable(BaseIterable):
"""
Iterable returned by QuerySet.values() that yields a dict for each row.
@@ -1994,41 +2038,7 @@ class RawQuerySet:
return iter(self._result_cache)
def iterator(self):
- # Cache some things for performance reasons outside the loop.
- db = self.db
- connection = connections[db]
- compiler = connection.ops.compiler("SQLCompiler")(self.query, connection, db)
- query = iter(self.query)
-
- try:
- (
- model_init_names,
- model_init_pos,
- annotation_fields,
- ) = self.resolve_model_init_order()
- if self.model._meta.pk.attname not in model_init_names:
- raise exceptions.FieldDoesNotExist(
- "Raw query must include the primary key"
- )
- model_cls = self.model
- fields = [self.model_fields.get(c) for c in self.columns]
- converters = compiler.get_converters(
- [f.get_col(f.model._meta.db_table) if f else None for f in fields]
- )
- if converters:
- query = compiler.apply_converters(query, converters)
- for values in query:
- # Associate fields to values
- model_init_values = [values[pos] for pos in model_init_pos]
- instance = model_cls.from_db(db, model_init_names, model_init_values)
- if annotation_fields:
- for column, pos in annotation_fields:
- setattr(instance, column, values[pos])
- yield instance
- finally:
- # Done iterating the Query. If it has its own cursor, close it.
- if hasattr(self.query, "cursor") and self.query.cursor:
- self.query.cursor.close()
+ yield from RawModelIterable(self)
def __repr__(self):
return "<%s: %s>" % (self.__class__.__name__, self.query)
