mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Refs #33646 -- Added RawModelIterable.
This commit is contained in:
		| @@ -140,6 +140,50 @@ class ModelIterable(BaseIterable): | |||||||
|             yield obj |             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): | class ValuesIterable(BaseIterable): | ||||||
|     """ |     """ | ||||||
|     Iterable returned by QuerySet.values() that yields a dict for each row. |     Iterable returned by QuerySet.values() that yields a dict for each row. | ||||||
| @@ -1994,41 +2038,7 @@ class RawQuerySet: | |||||||
|         return iter(self._result_cache) |         return iter(self._result_cache) | ||||||
|  |  | ||||||
|     def iterator(self): |     def iterator(self): | ||||||
|         # Cache some things for performance reasons outside the loop. |         yield from RawModelIterable(self) | ||||||
|         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() |  | ||||||
|  |  | ||||||
|     def __repr__(self): |     def __repr__(self): | ||||||
|         return "<%s: %s>" % (self.__class__.__name__, self.query) |         return "<%s: %s>" % (self.__class__.__name__, self.query) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user