From e93f56b174b6105943b68dfc3d2b81ccdc3c364a Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Tue, 13 Apr 2010 15:18:10 +0000 Subject: [PATCH] Fixed #13227 -- Ensure that the query cache is flushed when a QuerySet is deepcopied, avoiding problems when an evaluated queryset is used as a subquery. Thanks to claudep for the report. git-svn-id: http://code.djangoproject.com/svn/django/trunk@12970 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/db/models/query.py | 9 +++++---- tests/regressiontests/queries/tests.py | 20 +++++++++++++++++++- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/django/db/models/query.py b/django/db/models/query.py index ad6d37f631..dfb894930b 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -45,11 +45,12 @@ class QuerySet(object): """ Deep copy of a QuerySet doesn't populate the cache """ - obj_dict = deepcopy(self.__dict__, memo) - obj_dict['_iter'] = None - obj = self.__class__() - obj.__dict__.update(obj_dict) + for k,v in self.__dict__.items(): + if k in ('_iter','_result_cache'): + obj.__dict__[k] = None + else: + obj.__dict__[k] = deepcopy(v, memo) return obj def __getstate__(self): diff --git a/tests/regressiontests/queries/tests.py b/tests/regressiontests/queries/tests.py index ee79a9f85a..03c28b06a7 100644 --- a/tests/regressiontests/queries/tests.py +++ b/tests/regressiontests/queries/tests.py @@ -4,7 +4,7 @@ from django.db import DatabaseError, connections, DEFAULT_DB_ALIAS from django.db.models import Count from django.test import TestCase -from models import Tag, Annotation, DumbCategory +from models import Tag, Annotation, DumbCategory, Note, ExtraInfo class QuerysetOrderedTests(unittest.TestCase): """ @@ -63,3 +63,21 @@ class SubqueryTests(TestCase): # This prevents us from even evaluating this test case at all. # Refs #10099 self.assertFalse(connections[DEFAULT_DB_ALIAS].features.allow_sliced_subqueries) + +class CloneTests(TestCase): + def test_evaluated_queryset_as_argument(self): + "#13227 -- If a queryset is already evaluated, it can still be used as a query arg" + n = Note(note='Test1', misc='misc') + n.save() + e = ExtraInfo(info='good', note=n) + e.save() + + n_list = Note.objects.all() + # Evaluate the Note queryset, populating the query cache + list(n_list) + # Use the note queryset in a query, and evalute + # that query in a way that involves cloning. + try: + self.assertEquals(ExtraInfo.objects.filter(note__in=n_list)[0].info, 'good') + except: + self.fail('Query should be clonable')