mirror of https://github.com/django/django.git
Fixed #29339 -- Added result caching to RawQuerySet.
This commit is contained in:
parent
c1c163b427
commit
ec0319ff82
|
@ -1277,6 +1277,7 @@ class RawQuerySet:
|
||||||
self.query = query or sql.RawQuery(sql=raw_query, using=self.db, params=params)
|
self.query = query or sql.RawQuery(sql=raw_query, using=self.db, params=params)
|
||||||
self.params = params or ()
|
self.params = params or ()
|
||||||
self.translations = translations or {}
|
self.translations = translations or {}
|
||||||
|
self._result_cache = None
|
||||||
|
|
||||||
def resolve_model_init_order(self):
|
def resolve_model_init_order(self):
|
||||||
"""Resolve the init field names and value positions."""
|
"""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]
|
model_init_names = [f.attname for f in model_init_fields]
|
||||||
return model_init_names, model_init_order, annotation_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):
|
def __iter__(self):
|
||||||
|
self._fetch_all()
|
||||||
|
return iter(self._result_cache)
|
||||||
|
|
||||||
|
def iterator(self):
|
||||||
# Cache some things for performance reasons outside the loop.
|
# Cache some things for performance reasons outside the loop.
|
||||||
db = self.db
|
db = self.db
|
||||||
compiler = connections[db].ops.compiler('SQLCompiler')(
|
compiler = connections[db].ops.compiler('SQLCompiler')(
|
||||||
|
|
|
@ -401,6 +401,9 @@ Miscellaneous
|
||||||
* The admin CSS class ``field-box`` is renamed to ``fieldBox`` to prevent
|
* The admin CSS class ``field-box`` is renamed to ``fieldBox`` to prevent
|
||||||
conflicts with the class given to model fields named "box".
|
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:
|
.. _deprecated-features-2.1:
|
||||||
|
|
||||||
Features deprecated in 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
|
:class:`~django.db.models.query.QuerySet`, ``RawQuerySet`` doesn't
|
||||||
implement all methods you can use with ``QuerySet``. For example,
|
implement all methods you can use with ``QuerySet``. For example,
|
||||||
``__bool__()`` and ``__len__()`` are not defined in ``RawQuerySet``, and
|
``__bool__()`` and ``__len__()`` are not defined in ``RawQuerySet``, and
|
||||||
thus all ``RawQuerySet`` instances are considered ``True``. The reason
|
thus all ``RawQuerySet`` instances are considered ``True``.
|
||||||
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.
|
|
||||||
|
|
||||||
Mapping query fields to model fields
|
Mapping query fields to model fields
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
|
@ -318,3 +318,15 @@ class RawQueryTests(TestCase):
|
||||||
c = Coffee.objects.create(brand='starbucks', price=20.5)
|
c = Coffee.objects.create(brand='starbucks', price=20.5)
|
||||||
qs = Coffee.objects.raw("SELECT * FROM raw_query_coffee WHERE price >= %s", params=[Decimal(20)])
|
qs = Coffee.objects.raw("SELECT * FROM raw_query_coffee WHERE price >= %s", params=[Decimal(20)])
|
||||||
self.assertEqual(list(qs), [c])
|
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())
|
||||||
|
|
Loading…
Reference in New Issue