Fixed #19816: pre-evaluate queryset on m2m set

In ReverseManyRelatedObjectsDescriptor.__set__, evaluate possible
queryset to avoid problems when clear() would touch data this queryset
returns.
This commit is contained in:
Tomek Paczkowski 2013-02-23 15:50:33 +01:00
parent 1b7fb29dfb
commit 3dddbc0f23
2 changed files with 17 additions and 1 deletions

View File

@ -904,6 +904,9 @@ class ReverseManyRelatedObjectsDescriptor(object):
raise AttributeError("Cannot set values on a ManyToManyField which specifies an intermediary model. Use %s.%s's Manager instead." % (opts.app_label, opts.object_name)) raise AttributeError("Cannot set values on a ManyToManyField which specifies an intermediary model. Use %s.%s's Manager instead." % (opts.app_label, opts.object_name))
manager = self.__get__(instance) manager = self.__get__(instance)
# clear() can change expected output of 'value' queryset, we force evaluation
# of queryset before clear; ticket #19816
value = tuple(value)
manager.clear() manager.clear()
manager.add(*value) manager.add(*value)

View File

@ -5,7 +5,7 @@ from django.test import TestCase
from django.utils import six from django.utils import six
from .models import (SelfRefer, Tag, TagCollection, Entry, SelfReferChild, from .models import (SelfRefer, Tag, TagCollection, Entry, SelfReferChild,
SelfReferChildSibling, Worksheet, RegressionModelSplit) SelfReferChildSibling, Worksheet, RegressionModelSplit, Line)
class M2MRegressionTests(TestCase): class M2MRegressionTests(TestCase):
@ -96,3 +96,16 @@ class M2MRegressionTests(TestCase):
# causes a TypeError in add_lazy_relation # causes a TypeError in add_lazy_relation
m1 = RegressionModelSplit(name='1') m1 = RegressionModelSplit(name='1')
m1.save() m1.save()
def test_m2m_filter(self):
worksheet = Worksheet.objects.create(id=1)
line_hi = Line.objects.create(name="hi")
line_bye = Line.objects.create(name="bye")
worksheet.lines = [line_hi, line_bye]
hi = worksheet.lines.filter(name="hi")
worksheet.lines = hi
self.assertEquals(1, worksheet.lines.count())
self.assertEquals(1, hi.count())