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.
This commit is contained in:
parent
73f38eb4d1
commit
b4cd8169de
|
@ -768,6 +768,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)
|
||||||
|
|
|
@ -15,6 +15,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 .models import (
|
from .models import (
|
||||||
Annotation, Article, Author, Celebrity, Child, Cover, Detail, DumbCategory,
|
Annotation, Article, Author, Celebrity, Child, Cover, Detail, DumbCategory,
|
||||||
|
@ -969,7 +970,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.
|
||||||
|
@ -1279,6 +1280,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