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
This commit is contained in:
Russell Keith-Magee 2010-04-13 15:18:10 +00:00
parent b3390fede0
commit e93f56b174
2 changed files with 24 additions and 5 deletions

View File

@ -45,11 +45,12 @@ class QuerySet(object):
""" """
Deep copy of a QuerySet doesn't populate the cache Deep copy of a QuerySet doesn't populate the cache
""" """
obj_dict = deepcopy(self.__dict__, memo)
obj_dict['_iter'] = None
obj = self.__class__() 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 return obj
def __getstate__(self): def __getstate__(self):

View File

@ -4,7 +4,7 @@ from django.db import DatabaseError, connections, DEFAULT_DB_ALIAS
from django.db.models import Count from django.db.models import Count
from django.test import TestCase from django.test import TestCase
from models import Tag, Annotation, DumbCategory from models import Tag, Annotation, DumbCategory, Note, ExtraInfo
class QuerysetOrderedTests(unittest.TestCase): class QuerysetOrderedTests(unittest.TestCase):
""" """
@ -63,3 +63,21 @@ class SubqueryTests(TestCase):
# This prevents us from even evaluating this test case at all. # This prevents us from even evaluating this test case at all.
# Refs #10099 # Refs #10099
self.assertFalse(connections[DEFAULT_DB_ALIAS].features.allow_sliced_subqueries) 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')