mirror of https://github.com/django/django.git
[1.6.x] Fixed #11811 -- Data-loss bug in queryset.update.
It's now forbidden to call queryset.update(field=instance) when instance
hasn't been saved to the database ie. instance.pk is None.
Conflicts:
tests/queries/tests.py
Backport of b4cd8169
from master.
This commit is contained in:
parent
2a2ac5c140
commit
f855058c35
|
@ -736,6 +736,8 @@ class Model(six.with_metaclass(ModelBase)):
|
||||||
return getattr(self, cachename)
|
return getattr(self, cachename)
|
||||||
|
|
||||||
def prepare_database_save(self, unused):
|
def prepare_database_save(self, unused):
|
||||||
|
if self.pk is None:
|
||||||
|
raise ValueError("Unsaved model instance %r cannot be used in an ORM query." % self)
|
||||||
return self.pk
|
return self.pk
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
|
|
|
@ -17,9 +17,13 @@ class ProxyCategory(DumbCategory):
|
||||||
class Meta:
|
class Meta:
|
||||||
proxy = True
|
proxy = True
|
||||||
|
|
||||||
|
@python_2_unicode_compatible
|
||||||
class NamedCategory(DumbCategory):
|
class NamedCategory(DumbCategory):
|
||||||
name = models.CharField(max_length=10)
|
name = models.CharField(max_length=10)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
class Tag(models.Model):
|
class Tag(models.Model):
|
||||||
name = models.CharField(max_length=10)
|
name = models.CharField(max_length=10)
|
||||||
|
|
|
@ -13,6 +13,7 @@ from django.db.models.sql.where import WhereNode, EverythingNode, NothingNode
|
||||||
from django.db.models.sql.datastructures import EmptyResultSet
|
from django.db.models.sql.datastructures import EmptyResultSet
|
||||||
from django.test import TestCase, skipUnlessDBFeature
|
from django.test import TestCase, skipUnlessDBFeature
|
||||||
from django.test.utils import str_prefix
|
from django.test.utils import str_prefix
|
||||||
|
from django.utils import six
|
||||||
from django.utils import unittest
|
from django.utils import unittest
|
||||||
from django.utils.datastructures import SortedDict
|
from django.utils.datastructures import SortedDict
|
||||||
|
|
||||||
|
@ -957,7 +958,7 @@ class Queries1Tests(BaseQuerysetTest):
|
||||||
q = NamedCategory.objects.filter(tag__parent__isnull=True)
|
q = NamedCategory.objects.filter(tag__parent__isnull=True)
|
||||||
self.assertTrue(str(q.query).count('INNER JOIN') == 1)
|
self.assertTrue(str(q.query).count('INNER JOIN') == 1)
|
||||||
self.assertTrue(str(q.query).count('LEFT OUTER JOIN') == 1)
|
self.assertTrue(str(q.query).count('LEFT OUTER JOIN') == 1)
|
||||||
self.assertQuerysetEqual( q, ['<NamedCategory: NamedCategory object>'])
|
self.assertQuerysetEqual(q, ['<NamedCategory: Generic>'])
|
||||||
|
|
||||||
def test_ticket_10790_4(self):
|
def test_ticket_10790_4(self):
|
||||||
# Querying across m2m field should not strip the m2m table from join.
|
# Querying across m2m field should not strip the m2m table from join.
|
||||||
|
@ -1267,6 +1268,13 @@ class Queries4Tests(BaseQuerysetTest):
|
||||||
Item.objects.create(name='i1', created=datetime.datetime.now(), note=n1, creator=self.a1)
|
Item.objects.create(name='i1', created=datetime.datetime.now(), note=n1, creator=self.a1)
|
||||||
Item.objects.create(name='i2', created=datetime.datetime.now(), note=n1, creator=self.a3)
|
Item.objects.create(name='i2', created=datetime.datetime.now(), note=n1, creator=self.a3)
|
||||||
|
|
||||||
|
def test_ticket11811(self):
|
||||||
|
unsaved_category = NamedCategory(name="Other")
|
||||||
|
with six.assertRaisesRegex(self, ValueError,
|
||||||
|
'Unsaved model instance <NamedCategory: Other> '
|
||||||
|
'cannot be used in an ORM query.'):
|
||||||
|
Tag.objects.filter(pk=self.t1.pk).update(category=unsaved_category)
|
||||||
|
|
||||||
def test_ticket14876(self):
|
def test_ticket14876(self):
|
||||||
# Note: when combining the query we need to have information available
|
# Note: when combining the query we need to have information available
|
||||||
# about the join type of the trimmed "creator__isnull" join. If we
|
# about the join type of the trimmed "creator__isnull" join. If we
|
||||||
|
|
Loading…
Reference in New Issue