summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Chainz <adam@adamj.eu>2016-11-16 14:49:20 +0000
committerTim Graham <timograham@gmail.com>2016-11-23 11:23:14 -0500
commite044026dce063ec53c16d0f755ec75eb8c84b318 (patch)
tree8e446d814936295d2f66573533981e47039f45f2
parent7dd315a46f8e9a6fdb904424542c6f67a57edfa3 (diff)
downloaddjango-e044026dce063ec53c16d0f755ec75eb8c84b318.tar.gz
Fixed #27499 -- Made Prefetches pickle without evaluating their QuerySet.
-rw-r--r--django/db/models/query.py10
-rw-r--r--tests/queryset_pickle/tests.py9
2 files changed, 19 insertions, 0 deletions
diff --git a/django/db/models/query.py b/django/db/models/query.py
index b6449582b2..9497cb3ce6 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -1289,6 +1289,16 @@ class Prefetch(object):
self.queryset = queryset
self.to_attr = to_attr
+ def __getstate__(self):
+ obj_dict = self.__dict__.copy()
+ if self.queryset is not None:
+ # Prevent the QuerySet from being evaluated
+ obj_dict['queryset'] = self.queryset._clone(
+ _result_cache=[],
+ _prefetch_done=True,
+ )
+ return obj_dict
+
def add_prefix(self, prefix):
self.prefetch_through = LOOKUP_SEP.join([prefix, self.prefetch_through])
self.prefetch_to = LOOKUP_SEP.join([prefix, self.prefetch_to])
diff --git a/tests/queryset_pickle/tests.py b/tests/queryset_pickle/tests.py
index 37069cf286..d95878966a 100644
--- a/tests/queryset_pickle/tests.py
+++ b/tests/queryset_pickle/tests.py
@@ -134,6 +134,15 @@ class PickleabilityTestCase(TestCase):
groups2 = pickle.loads(pickle.dumps(groups))
self.assertSequenceEqual(groups2.filter(id__gte=0), [g])
+ def test_pickle_prefetch_queryset_not_evaluated(self):
+ Group.objects.create(name='foo')
+ groups = Group.objects.prefetch_related(
+ models.Prefetch('event_set', queryset=Event.objects.order_by('id'))
+ )
+ list(groups) # evaluate QuerySet
+ with self.assertNumQueries(0):
+ pickle.loads(pickle.dumps(groups))
+
def test_pickle_prefetch_related_with_m2m_and_objects_deletion(self):
"""
#24831 -- Cached properties on ManyToOneRel created in QuerySet.delete()