Fixed #27710 -- Made Model.save() invalidate cached, stale relations after a primary key assignment.

This commit is contained in:
Paulo 2017-09-20 23:27:04 -05:00 committed by Tim Graham
parent ebb998976e
commit ee49306176
3 changed files with 24 additions and 0 deletions

View File

@ -674,6 +674,10 @@ class Model(metaclass=ModelBase):
"save() prohibited to prevent data loss due to "
"unsaved related object '%s'." % field.name
)
# If the relationship's pk was changed, clear the cached
# relationship.
if obj and obj.pk != getattr(self, field.attname):
field.delete_cached_value(self)
using = using or router.db_for_write(self.__class__, instance=self)
if force_insert and (force_update or update_fields):

View File

@ -656,3 +656,13 @@ class ManyToOneTests(TestCase):
self.assertEqual(city.districts.count(), 2)
city.districts.remove(d2)
self.assertEqual(city.districts.count(), 1)
def test_cached_relation_invalidated_on_save(self):
"""
Model.save() invalidates stale ForeignKey relations after a primary key
assignment.
"""
self.assertEqual(self.a.reporter, self.r) # caches a.reporter
self.a.reporter_id = self.r2.pk
self.a.save()
self.assertEqual(self.a.reporter, self.r2)

View File

@ -507,3 +507,13 @@ class OneToOneTests(TestCase):
pointer = ToFieldPointer.objects.create(target=target)
self.assertSequenceEqual(ToFieldPointer.objects.filter(target=target), [pointer])
self.assertSequenceEqual(ToFieldPointer.objects.filter(pk__exact=pointer), [pointer])
def test_cached_relation_invalidated_on_save(self):
"""
Model.save() invalidates stale OneToOneField relations after a primary
key assignment.
"""
self.assertEqual(self.b1.place, self.p1) # caches b1.place
self.b1.place_id = self.p2.pk
self.b1.save()
self.assertEqual(self.b1.place, self.p2)