mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #29339 -- Added result caching to RawQuerySet.
This commit is contained in:
		| @@ -1277,6 +1277,7 @@ class RawQuerySet: | ||||
|         self.query = query or sql.RawQuery(sql=raw_query, using=self.db, params=params) | ||||
|         self.params = params or () | ||||
|         self.translations = translations or {} | ||||
|         self._result_cache = None | ||||
|  | ||||
|     def resolve_model_init_order(self): | ||||
|         """Resolve the init field names and value positions.""" | ||||
| @@ -1288,7 +1289,15 @@ class RawQuerySet: | ||||
|         model_init_names = [f.attname for f in model_init_fields] | ||||
|         return model_init_names, model_init_order, annotation_fields | ||||
|  | ||||
|     def _fetch_all(self): | ||||
|         if self._result_cache is None: | ||||
|             self._result_cache = list(self.iterator()) | ||||
|  | ||||
|     def __iter__(self): | ||||
|         self._fetch_all() | ||||
|         return iter(self._result_cache) | ||||
|  | ||||
|     def iterator(self): | ||||
|         # Cache some things for performance reasons outside the loop. | ||||
|         db = self.db | ||||
|         compiler = connections[db].ops.compiler('SQLCompiler')( | ||||
|   | ||||
| @@ -401,6 +401,9 @@ Miscellaneous | ||||
| * The admin CSS class ``field-box`` is renamed to ``fieldBox`` to prevent | ||||
|   conflicts with the class given to model fields named "box". | ||||
|  | ||||
| * ``QuerySet.raw()`` now caches its results like regular querysets. Use | ||||
|   ``iterator()`` if you don't want caching. | ||||
|  | ||||
| .. _deprecated-features-2.1: | ||||
|  | ||||
| Features deprecated in 2.1 | ||||
|   | ||||
| @@ -91,10 +91,7 @@ options that make it very powerful. | ||||
|     :class:`~django.db.models.query.QuerySet`, ``RawQuerySet`` doesn't | ||||
|     implement all methods you can use with ``QuerySet``. For example, | ||||
|     ``__bool__()`` and ``__len__()`` are not defined in ``RawQuerySet``, and | ||||
|     thus all ``RawQuerySet`` instances are considered ``True``. The reason | ||||
|     these methods are not implemented in ``RawQuerySet`` is that implementing | ||||
|     them without internal caching would be a performance drawback and adding | ||||
|     such caching would be backward incompatible. | ||||
|     thus all ``RawQuerySet`` instances are considered ``True``. | ||||
|  | ||||
| Mapping query fields to model fields | ||||
| ------------------------------------ | ||||
|   | ||||
| @@ -318,3 +318,15 @@ class RawQueryTests(TestCase): | ||||
|         c = Coffee.objects.create(brand='starbucks', price=20.5) | ||||
|         qs = Coffee.objects.raw("SELECT * FROM raw_query_coffee WHERE price >= %s", params=[Decimal(20)]) | ||||
|         self.assertEqual(list(qs), [c]) | ||||
|  | ||||
|     def test_result_caching(self): | ||||
|         with self.assertNumQueries(1): | ||||
|             books = Book.objects.raw('SELECT * FROM raw_query_book') | ||||
|             list(books) | ||||
|             list(books) | ||||
|  | ||||
|     def test_iterator(self): | ||||
|         with self.assertNumQueries(2): | ||||
|             books = Book.objects.raw('SELECT * FROM raw_query_book') | ||||
|             list(books.iterator()) | ||||
|             list(books.iterator()) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user