mirror of
				https://github.com/django/django.git
				synced 2025-10-31 01:25:32 +00:00 
			
		
		
		
	Refs #33646 -- Added RawModelIterable.
This commit is contained in:
		| @@ -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) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user