Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

[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 b4cd816 from master.
  • Loading branch information...
commit f855058c35db9d35ba7f310d8f9db6f4533b7424 1 parent 2a2ac5c
@aaugustin aaugustin authored
View
2  django/db/models/base.py
@@ -736,6 +736,8 @@ def _get_next_or_previous_in_order(self, is_next):
return getattr(self, cachename)
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
def clean(self):
View
4 tests/queries/models.py
@@ -17,9 +17,13 @@ class ProxyCategory(DumbCategory):
class Meta:
proxy = True
+@python_2_unicode_compatible
class NamedCategory(DumbCategory):
name = models.CharField(max_length=10)
+ def __str__(self):
+ return self.name
+
@python_2_unicode_compatible
class Tag(models.Model):
name = models.CharField(max_length=10)
View
10 tests/queries/tests.py
@@ -13,6 +13,7 @@
from django.db.models.sql.datastructures import EmptyResultSet
from django.test import TestCase, skipUnlessDBFeature
from django.test.utils import str_prefix
+from django.utils import six
from django.utils import unittest
from django.utils.datastructures import SortedDict
@@ -957,7 +958,7 @@ def test_ticket_10790_3(self):
q = NamedCategory.objects.filter(tag__parent__isnull=True)
self.assertTrue(str(q.query).count('INNER 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):
# Querying across m2m field should not strip the m2m table from join.
@@ -1267,6 +1268,13 @@ def setUp(self):
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)
+ 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):
# Note: when combining the query we need to have information available
# about the join type of the trimmed "creator__isnull" join. If we
Please sign in to comment.
Something went wrong with that request. Please try again.