From 136bf5c2142ae3261669d02e2dd050c3141f7f2f Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Tue, 30 Jan 2018 07:43:53 -0800 Subject: [PATCH] Fixed #29076 -- Made Model.refresh_from_db() clear cached relationships even if the related id doesn't change. --- django/db/models/base.py | 8 ++------ docs/ref/models/instances.txt | 7 +------ tests/basic/tests.py | 12 ++++++++++++ 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/django/db/models/base.py b/django/db/models/base.py index f88690f225..8d4e19fa5a 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -609,13 +609,9 @@ class Model(metaclass=ModelBase): # This field wasn't refreshed - skip ahead. continue setattr(self, field.attname, getattr(db_instance, field.attname)) - # Throw away stale foreign key references. + # Clear cached foreign keys. if field.is_relation and field.is_cached(self): - rel_instance = field.get_cached_value(self) - local_val = getattr(db_instance, field.attname) - related_val = None if rel_instance is None else getattr(rel_instance, field.target_field.attname) - if local_val != related_val or (local_val is None and related_val is None): - field.delete_cached_value(self) + field.delete_cached_value(self) # Clear cached relations. for field in self._meta.related_objects: diff --git a/docs/ref/models/instances.txt b/docs/ref/models/instances.txt index c327b0e9e7..73bbeb8f31 100644 --- a/docs/ref/models/instances.txt +++ b/docs/ref/models/instances.txt @@ -137,12 +137,7 @@ following is done: 1. All non-deferred fields of the model are updated to the values currently present in the database. -2. The previously loaded related instances for which the relation's value is no - longer valid are removed from the reloaded instance. For example, if you have - a foreign key from the reloaded instance to another model with name - ``Author``, then if ``obj.author_id != obj.author.id``, ``obj.author`` will - be thrown away, and when next accessed it will be reloaded with the value of - ``obj.author_id``. +2. Any cached relations are cleared from the reloaded instance. Only fields of the model are reloaded from the database. Other database-dependent values such as annotations aren't reloaded. Any diff --git a/tests/basic/tests.py b/tests/basic/tests.py index 7a99ab0cf0..1a5e95e9d6 100644 --- a/tests/basic/tests.py +++ b/tests/basic/tests.py @@ -722,3 +722,15 @@ class ModelRefreshTests(TestCase): FeaturedArticle.objects.create(article_id=article.pk) article.refresh_from_db() self.assertTrue(hasattr(article, 'featured')) + + def test_refresh_clears_one_to_one_field(self): + article = Article.objects.create( + headline='Parrot programs in Python', + pub_date=datetime(2005, 7, 28), + ) + featured = FeaturedArticle.objects.create(article_id=article.pk) + self.assertEqual(featured.article.headline, 'Parrot programs in Python') + article.headline = 'Parrot programs in Python 2.0' + article.save() + featured.refresh_from_db() + self.assertEqual(featured.article.headline, 'Parrot programs in Python 2.0')